Saving held items while player leaves

Hi,

I have a script that saves items in the players backpack into a table that will be accessed when the player rejoins, but the problem is whenever I hold the items and leave they don’t save.

I came to the conclusion that its because the item isn’t in the backpack anymore but in the character model, but no matter what i do to try to access the character after it leaves it does not work.

local inventoryStore = datastores:GetDataStore("InventoryData")

players.PlayerRemoving:Connect(function(player)
	local backpack = player:FindFirstChild("Backpack")
	if backpack then
		local items = {}
		for _, item in pairs(backpack:GetChildren()) do
			print(item)
			table.insert(items, item.Name)
		end
		
		if player then
			player.CharacterRemoving:Connect(function(character)
				for _, item in pairs(character:GetDescendants()) do
					if item:IsA('Tool') then 
					print(item.Name)
					table.insert(items, item.Name)
					end
				end
			end)
		end
		
	
		local yay, err = pcall(function()
			inventoryStore:SetAsync(player.UserId, items)
		end)
	
		if not yay then
			warn("Failed to save inventory for", player.Name, err)
		end
	end
end)

players.PlayerAdded:Connect(function(player)
	-- load the items
	local yay, items  = pcall(function()
		return inventoryStore:GetAsync(player.UserId)
	end)

	if yay and items then
		for _, itemName in pairs(items) do
			local itemTemplate = workspace.buyableItems:FindFirstChild(itemName)
			if itemTemplate then
				local clone = itemTemplate:Clone()
				clone.Handle.Anchored = false
				clone.Parent = player:WaitForChild("Backpack")
			end
		end
	end
end)

This is because you are connecting the CharacterRemoving event with the function after it is fired. In your case, there is no need to get the character through the removing event. Simply get the character via player.Character.

Also, you can simplify your code by getting the held tool with player.Character:FindFirstChildOfClass("Tool"). Since you can only have one held tool, there will only be one Tool in the character, removing the need for loops.

local character: Model? = player.Character

if character then
	local tool: Tool? = character:FindFirstChildOfClass("Tool")

	if tool then
		table.insert(items, tool.Name)
	end
end
2 Likes

As far as I know, this is the only way i can get the character because i am doing all of this in a server script. I don’t know how else i can grab the character.

You can get the character with player.Character on both the server and client. Try out the aforementioned method, it will work.

@ardrous 100% knows more than me, but incase you can’t get the character still, a sloppy solution would probably be to have something that keeps track when the player has a tool equipped, so you can just check that variable when saving to make sure you include their equipped tool before they left. (only if you can’t get the character for whatever reason, I’m assuming he already gave the solution, but just incase it isn’t)

Yes, i attempted that and i even added print statements to check if the tool was even being found. The entire character seems to just be gone before it can check for the tool.

to clarify this is what you meant correct?

local inventoryStore = datastores:GetDataStore("InventoryData")

players.PlayerRemoving:Connect(function(player)
	local backpack = player:FindFirstChild("Backpack")
	local character = player.Character
	if backpack then
		local items = {}
		for _, item in pairs(backpack:GetChildren()) do
			print(item)
			table.insert(items, item.Name)
		end
		


		if character then
			local tool = character:FindFirstChildOfClass('Tool')

			if tool then
				table.insert(items, tool.Name)
			end
		end

Ah I see, I misunderstood your followup question. In that case, similar to what @Ender_devTC mentioned, I would store the last equipped tool name. You can use character.ChildAdded and update the last equipped tool name for each player.

I believe what im trying to do just isnt possible. Ive tried every single thing under the sun that ive been recommended and it just does not work.

It’s important to make sure to also update when there is no tool being held, so you aren’t duping tools that were unequipped and are back in backpack. I also wonder if something like this would still allow for some perfectly timed equipping and unequipping that would have 2 copies of the same tool, so probably might need some basic security system that makes sure it doesn’t save the same tool twice.

Yeah, agreed. I think rather than keeping track of the tool being equipped, it would be much more reliable and efficient to keep track of all tools when they are first added to the backpack. When the player leaves, you will have an updated table of tool names that can be used. This method would make sure quickly equipping or unequipping tools would have no effect on saving.

I made a system to update it when it wasnt held as well and now it seems to work, thank you!

Thank you as well ardrous for your help!!

1 Like