Having problems with Tools saving in inventory when restarting/leaving/shutdowns

Hello, I am making a sword game and I have been trying to make a database that saves all the tools that a player either picks up or purchases but everything that happens doesn’t work.

local DEFAULT_TOOL = "StarterSword"

--// Services
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")

--// DataStore
local InventoryDataStore = DataStoreService:GetDataStore("PlayerToolInventory")

--// Folder containing all pickable tools
local ToolStorage = ReplicatedStorage:WaitForChild("ToolStorage")

--// Load saved tools
local function loadInventory(player)
	local tools = {}
	local success, data = pcall(function()
		return InventoryDataStore:GetAsync(player.UserId)
	end)

	-- Clean current tools
	for _, item in ipairs(player.Backpack:GetChildren()) do
		if item:IsA("Tool") then item:Destroy() end
	end

	if success and data then
		for _, toolName in pairs(data) do
			local toolTemplate = ToolStorage:FindFirstChild(toolName)
			if toolTemplate then
				local tool = toolTemplate:Clone()
				tool.Parent = player.Backpack
			end
		end
	end
end

--// Save tools to DataStore
local function saveInventory(player)
	local toolNames = {}
	local seen = {}

	for _, tool in ipairs(player.Backpack:GetChildren()) do
		if tool:IsA("Tool") and tool.Name ~= DEFAULT_TOOL and not seen[tool.Name] then
			table.insert(toolNames, tool.Name)
			seen[tool.Name] = true
		end
	end

	local success, err = pcall(function()
		InventoryDataStore:SetAsync(player.UserId, toolNames)
	end)

	if not success then
		warn("❌ Error saving inventory for", player.Name, ":", err)
	end
end

--// Player joined
Players.PlayerAdded:Connect(function(player)
	player.CharacterAdded:Connect(function()
		-- Give starter tool on spawn (not saved)
		local defaultTool = ToolStorage:FindFirstChild(DEFAULT_TOOL)
		if defaultTool then
			local tool = defaultTool:Clone()
			tool.Parent = player.Backpack
		end
	end)

	print("🔄 Loading tools for", player.Name, ":")
	loadInventory(player)
end)

--// Player leaving
Players.PlayerRemoving:Connect(function(player)
	saveInventory(player)
end)

--// Save everyone’s tools on shutdown
game:BindToClose(function()
	for _, player in ipairs(Players:GetPlayers()) do
		saveInventory(player)
	end
end)```
2 Likes

The issue is happening because you’re calling loadInventory before the character fully loads.

I’m not sure how your system is meant to handle inventory after respawning, but if you want the tools to appear correctly in the player’s Backpack, you’ll need to wait until the character has loaded before calling loadInventory (Ofcourse if they save after respawn, then put them into StarterGear)

This makes sure the tools are placed into the backpack after the character exist, preventing them from getting randomly vanished.

Other than those issues, I think the Datastore is set up really well overall.

2 Likes

I believe I have done it now I get this.

image

That means you’re calling WaitForChild("ToolStorage") on ReplicatedStorage, so make sure there’s actually a folder named ToolStorage inside ReplicatedStorage

If it’s missing or gets renamed, WaitForChild will cause a “Infinite yield”

2 Likes

Ok sorry, I sorted the naming problem out but it doesn’t save it still, output is acting like everything is good

1 Like

Do you have the tools inside of the ToolStorage ?

Yes it is in workspace i see how that can interfere with stuff