Tool data saving problem

  1. What do you want to achieve?
    I would really like to have some advice that would help me to solve the issue with my data saving with a tool held out instead of in the player’s backpack as everything that I have tried hasn’t worked.

  2. What is the issue?
    Most of the saving for example the items in the player’s backpack or inside the inventory UI works
    surprisingly well but the singular issue is saving the data for the tool held out.

  3. What solutions have you tried so far?
    I have tried many solutions such as saving directly by finding the child added into the character and saving it as the equipped tool and using remote events to also directly save it from the local script but that also failed miserably.

Here are some scripts that I mainly used for the data saving and loading:
The player added and removed functions:

plrs.PlayerAdded:Connect(function(plr)
	local loading = load(plr)
	if loading then
		local inv = game:GetService("ServerStorage"):WaitForChild("Inventory"):Clone()
		inv.Parent = plr
		local loading2 = loaditems(plr)
		setinv(plr)
		setcraft(plr)
	end
	local char = plr.Character
	char.ChildAdded:Connect(function(child)
		if child:IsA("Tool") then
			for i, v in pairs(data[plr.UserId]) do
				if v["Name"] == child.Name then
					print(child.Name .. " Equipped")
					v["Equipped"] = true
				end
			end
		end
	end)
	char.ChildRemoved:Connect(function(child)
		if child:IsA("Tool") then
			for i, v in pairs(data[plr.UserId]) do
				if v["Name"] == child.Name then
					print(child.Name .. " Unequipped")
					v["Equipped"] = false
				end
			end
		end
	end)
end)
plrs.PlayerRemoving:Connect(function(plr)
	save(plr)
	data[plr.UserId] = nil
end)

Data loading and item loading:

local function load(plr)
	local good = nil
	local plrdata = nil
	local attempt = 1
	repeat
		good, plrdata = pcall(function()
			return datastore:GetAsync(plr.UserId)
		end)
		attempt +=1
		if not good then
			warn(plrdata)
			task.wait()
		end
	until good or attempt == 3
	if good then
		print("data got")
		if not plrdata then
			print("new player, giving default")
			plrdata = {}
			for _, v in pairs(ss:WaitForChild("Inventory"):GetChildren()) do
				if v.Name == "Stick" then
					table.insert(plrdata, {
						["Name"] = v.Name,
						["Amount"] = 1,
						["Equipped"] = false
					})
				else
					if v:GetAttribute("CanEquip") == true then
						table.insert(plrdata, {
							["Name"] = v.Name,
							["Amount"] = 0,
							["Equipped"] = false
						})
					else
						table.insert(plrdata, {
							["Name"] = v.Name,
							["Amount"] = 0
						})
					end
				end
			end
			
		end
		data[plr.UserId] = plrdata
	else
		warn("Data Problem 2", plr.UserId)
		plr:Kick("Data Problem")
	end
	return "done"
end
local function loaditems(plr)
	local inv = plr:FindFirstChild("Inventory")
	local plrdata = data[plr.UserId]
	for i, v in pairs(plrdata) do
		if inv[v["Name"]] then
			inv:FindFirstChild(v["Name"]).Value = v["Amount"]
		end
	end
	return "done"
end

The data saving function:

local function save(plr, client)
	if data[plr.UserId] then
		for i, v in pairs(data[plr.UserId]) do
			if plr:FindFirstChild("Inventory")[v["Name"]]:GetAttribute("CanEquip") == true then
				v["Amount"] = plr:FindFirstChild("Inventory")[v["Name"]].Value
				if plr.Backpack:FindFirstChild(v["Name"]) then
					local tool = plr.Backpack:FindFirstChild(v["Name"])
					v["Amount"] = plr:FindFirstChild("Inventory")[tool.Name].Value + 1
				end
				if v["Equipped"] == true then
					v["Amount"] = plr:FindFirstChild("Inventory")[v["Name"]].Value + 1
				end
			else
				v["Amount"] = plr:FindFirstChild("Inventory")[v["Name"]].Value
			end
		end
		local good = nil
		local plrdata = nil
		local attempt = 1
		repeat
			good, plrdata = pcall(function()
				return datastore:UpdateAsync(plr.UserId, function()
					return data[plr.UserId]
				end)
			end)
			attempt +=1
			if not good then
				warn(plrdata)
				task.wait()
			end
		until good or attempt == 3
		if good then
			print("data saved")
		else
			warn("dont leave i didnt save yet", plr.UserId)
		end
	else
		print("nothing")
	end
end
'''
Some help with my coding would be extremely helpful, thank you.

If you already have a backpack-saving script, you could just use Humanoid:UnequipTools() so the tool will be saved with the rest of the backpack

That is one of the methods I used which somehow didn’t work.

Maybe the tool in the player’s character is being destroyed prior to the PlayerRemoving event. You could try and keep a table of all of the players tools while they’re playing.