Saving Equipped Tool

I’m working on a mining game, and I’ve already made a datastore to save the players inventory when they leave. But just recently, I noticed that the tool the player has equipped doesn’t save. Is there any way to fix this?

Datastore Script:
l

ocal DataStoreService = game:GetService("DataStoreService")
local InventoryDataStore = DataStoreService:GetDataStore("PlayerDataWithToolValues") 
local ToolsFolder = "Items" 


local function LoadInventory(player)
	local userId = tostring(player.UserId)
	local success, playerToolsData = pcall(function()
		return InventoryDataStore:GetAsync(userId)
	end)

	if success and playerToolsData then
		local toolsFolderInstance = game.ReplicatedStorage:WaitForChild(ToolsFolder)
		for itemName, toolInstancesData in playerToolsData do
			local toolTemplate = toolsFolderInstance:FindFirstChild(itemName)
			if toolTemplate then
				for _, instanceData in toolInstancesData do
					local clone = toolTemplate:Clone()
					if instanceData and instanceData.Values then
						for valueName, savedValue in instanceData.Values do
							local valueObject = clone:FindFirstChild(valueName)
							if valueObject and valueObject:IsA("ValueBase") then
								valueObject.Value = savedValue
							else
								warn("ToolsDataStore: Could not find ValueBase '" .. valueName .. "' in cloned tool '" .. itemName .. "' or it's not a ValueBase during load.")
							end
						end
					end
					clone.Parent = player.Backpack
				end
			else
				warn("ToolsDataStore: Could not find tool template '" .. itemName .. "' in ReplicatedStorage." .. ToolsFolder .. " during load.")
			end
		end
	else
		if not success then
			warn("ToolsDataStore: Failed to load inventory for player " .. player.Name .. ": " .. tostring(playerToolsData)) 
		end

	end
end

local function SaveInventory(player)
	local playerToolsData = {}

	local function processTool(toolInstance)
		if toolInstance:IsA("Tool") then
			local itemName = toolInstance.Name
			if not playerToolsData[itemName] then
				playerToolsData[itemName] = {}
			end

			local currentToolValues = {}
			for _, child in toolInstance:GetChildren() do
				if child:IsA("ValueBase") then
					currentToolValues[child.Name] = child.Value
				end
			end
			table.insert(playerToolsData[itemName], { Values = currentToolValues })
		end
	end


	if player and player.Backpack then
		for _, tool in player.Backpack:GetChildren() do
			processTool(tool)
		end
	end


	if player and player.Character then
		for _, tool in player.Character:GetChildren() do
			processTool(tool)
		end
	end

	if #playerToolsData == 0 and not next(playerToolsData) then 


	end

	local userId = tostring(player.UserId)
	local success, errorMsg = pcall(function()
		InventoryDataStore:SetAsync(userId, playerToolsData)
	end)

	if not success then
		warn("ToolsDataStore: Failed to save inventory for player " .. player.Name .. ": " .. errorMsg)
	end
end

local function SetupCharacter(player, character)
    LoadInventory(player)

 
    character.ChildAdded:Connect(function(child)
        if child:IsA("Tool") then
            SaveInventory(player)
        end
    end)


    character.ChildRemoved:Connect(function(child)
        if child:IsA("Tool") then
            SaveInventory(player)
        end
    end)



    local humanoid = character:FindFirstChildOfClass("Humanoid")
    if humanoid then
        humanoid.Died:Connect(function()
            SaveInventory(player)
        end)
    end
end

local function InitializePlayer(player)
    player.CharacterAdded:Connect(function(character)
        SetupCharacter(player, character)
    end)

    if player.Character then
        SetupCharacter(player, player.Character)
    end
end

local function OnPlayerRemoving(player)
	SaveInventory(player)
end


game.Players.PlayerAdded:Connect(InitializePlayer)
game.Players.PlayerRemoving:Connect(OnPlayerRemoving)


for _, player in game.Players:GetPlayers() do
	InitializePlayer(player)
end

All help is appreciated. Thank you!

Do you get any errors in your console?

no errors; just says that it loaded my inventory

local function SaveInventory(player)
    player.Character.Humanoid:UnequipTools()
	local playerToolsData = {}

wouldn’t that only work for if the player dies?

I also came across an issue like this working on my game. My solution was to just cache all of the tools that were added and removed from the players character and players backpack.

The reason it doesn’t save when equipped (I believe) is because of the removal of the character before saving (at least this is my assumption).

I use a combination of child added and child removed events to detect if a tool has ACTUALLY been removed or if it was just equipped to the character

so instead of checking the backpack and character individually for tools, you would just check that players specific tool instance table, which is not cleared until you need it to be.

In my specific case, I stored each tool as a dictionary inside of a players tool table, so I could access a tool like this: PlayerTools[player][tool]

(sorry if this was not explained well enough)

yeah i tried something like this and it kinda worked, except it would save every time the player had an item equipped, so if they sold the item they would just get it when they rejoined. ill keep this in mind when i try to fix it again

when a player has a tool equipped, it is parented to the character rather than the backpack.
you can try adding this code to your save logic

local tool = player.Character:FindFirstChildOfClass("Tool")
if tool then -- Make sure the player actually has a tool equipped
    processTool(tool)
end

just added something like this to the script and took other ideas from this into consideration and its finally working. thank you!

1 Like