How do I save a player's inventory (tools) when tool is equipped on leaving/dying?

What’s up bros. I have a datastore script that saves the player’s backpack to a datastore. The problem is, it doesn’t save a tool if it is equipped, because when a tool is equipped it goes to the player’s character instead of their backpack. The same is when a player dies with the tool equiped, it doesn’t save. I’m trying to save the player’s items at all times.

I’ve tried using Humanoid:UnequipTools() but it always breaks the script. I would really appreciate any help on this issue! If I solve this issue then my game is pretty much perfect lol.

Here’s my current datastore script, I have a folder called “Items” in serverstorage:

local folders_to_save = {

	-- 'Backpack' is the name of player's folder where items are stored
	-- And Items are the folder for where the items are originated

	['Backpack'] = game.ServerStorage.Items
}

-- Reload the saved items every time player respawns
local reload_items_on_reset = true

local DataStoreService = game:GetService("DataStoreService")
local ItemStore = DataStoreService:GetDataStore("ItemStore")

-- This is where we store all the loaded data's
local PlayerData = {}

local function LoadItemsFromData(player: Player, data, onReset: boolean)
	local folders = {}

	for storeFolderName, itemsFolder in pairs(folders_to_save) do
		local folder = player:FindFirstChild(storeFolderName)
		if not folder then
			-- the folder does not exist, so we create it
			folder = Instance.new("Folder")
			folder.Name = storeFolderName
			folder.Parent = player
		end
		-- keeping track of the folder
		folders[storeFolderName] = folder
	end

	-- now we're going to make a function to add items in data
	local function AddItem(item: Instance, folder: Folder, index: number)

		-- the data doesn't have the directory for the folder
		if not data[folder.Name] then
			-- we create it
			data[folder.Name] = {}
		end

		-- if the item wasn't exist in data
		if not index then
			-- getting the index of next to the very last index
			index = #data[folder.Name] + 1
			-- inserting the item name to data
			table.insert(data[folder.Name], index, item.Name)
		end


		-- detecting item parent change
		item.AncestryChanged:Connect(function(_, newParent)
			-- if item is not in the folder anymore
			-- and its not because player is resetting
			if newParent ~= folder and folder.Parent ~= nil then
				data[folder.Name][index] = nil
			end
		end)
	end

	-- iterating every item directory of the data
	for storeFolderName, savedItems in pairs(data) do

		-- if player is respawning, and folder is not Backpack
		-- we cancel the iteration
		--
		-- this is because only Backpack is being resetted
		-- after player respawn
		--
		-- other folder doesnt
		-- (btw this script supports not only backpack to save)
		-- (it also supports saving other kind of folders)
		-- (as long it is inside player)
		if onReset == true and storeFolderName ~= 'Backpack' then
			continue
		end


		local itemsFolder: Folder = folders_to_save[storeFolderName]

		-- checking if the directory has the items folder
		-- (where the items originated)
		if itemsFolder then

			-- getting the folder from player
			local folder = folders[storeFolderName]

			for index, itemName in pairs(savedItems) do
				-- checking if theres an item in the original items folder
				local item = itemsFolder:FindFirstChild(itemName)
				if item then
					-- cloning the item and put it the player's folder
					local playerItem = item:Clone()
					playerItem.Parent = folder

					-- since the item is exist in data, and has an index
					-- we pass that index in the parameter. and we will modify
					-- the additem function again
					AddItem(playerItem, folder, index)
				else
					-- if the item is not valid in the items folder
					warn(player, 'has unknown item that is said to be in folder', storeFolderName, ":", itemName)
				end
			end

		else
			warn(player, 'has unknown directory saved in data:', storeFolderName)
		end
	end

	-- now we loaded saved items to player's folder
	-- next is we detect of new items added in player folders

	for storeFolderName, folder in pairs(folders) do
		-- we dont need to track the folder anymore
		folders[storeFolderName] = nil

		-- we also need this here
		-- so the item added detector dont run twice
		if onReset == true and storeFolderName ~= 'Backpack' then
			continue
		end

		folder.ChildAdded:Connect(function(item)
			-- we dont have an index, so we leave it empty
			-- it means that the item will be added in data
			-- if it doesnt have an index
			AddItem(item, folder)
		end)
	end
end

-- a function to load player's data
local function Load(player: Player)

	-- if player's data is already loaded, cancel the function
	if PlayerData[player] then
		return warn(player, 'data is already loaded')
	end

	-- The key to access player's data
	local dataKey = 'key_' .. player.UserId

	-- always use pcall for async functions
	local loadedData = nil
	local success, result = pcall(function()
		-- getting the data from ItemStore Datastore
		loadedData = ItemStore:GetAsync(dataKey)
	end)

	-- error occured when loading data, and logging that error in the output
	if not success then
		error(success)
	end

	-- if player is new to the game, they dont have a saved data so its nil
	if loadedData == nil then
		loadedData = {} -- we give it empty data
	end

	warn(player, 'items have been loaded')

	return loadedData
end

local function Save(player: Player)
	local dataKey = 'key_' .. player.UserId

	-- get the tracked loaded data of the player
	local data = PlayerData[player]

	local success, result = pcall(function()
		ItemStore:SetAsync(dataKey, data, {player.UserId})
	end)

	-- something wrong/error happened
	if not success then
		error(result)
	end

	warn('Successfully saved', player, 'items to Datastore')
end

-- handling joining players
game.Players.PlayerAdded:Connect(function(player: Player)
	-- loading the data
	local data = Load(player)
	-- keep track of the data in PlayerData
	PlayerData[player] = data

	-- now we use the LoadItemsFromData function here
	-- waiting until character is loaded
	local character = player.Character or player.CharacterAdded:Wait()
	LoadItemsFromData(player, data)

	if reload_items_on_reset == true then
		player.CharacterAdded:Connect(function(character: Model)
			-- we pass true here to tell that the character respawned
			-- so we going to modify the LoadItemsFromData function
			LoadItemsFromData(player, data, true)
		end)    
	end
end)

game.Players.PlayerRemoving:Connect(function(player: Player)
	Save(player)

	-- player is leaving, so we dont need their data anymore
	-- get rid of it to prevent memory leak

	if PlayerData[player] then
		table.clear(PlayerData[player])
	end

	PlayerData[player] = nil
end)

-- at very last
game:BindToClose(function()
	-- if the game is closing, we will force save all player data
	for _, player in pairs(game.Players:GetPlayers()) do
		Save(player)
	end
end)
1 Like

Adjust the save function to ensure that equipped tools are also considered. This involves checking the player’s character for any tools and temporarily parenting them to the backpack for the save operation. Here’s how you might adjust your save logic:

local function Save(player: Player)
    local character = player.Character or player.CharacterAdded:Wait()
    local backpack = player:FindFirstChild("Backpack")
    if not backpack then
        warn("Backpack not found for", player.Name)
        return
    end

    -- Temporarily move equipped tools to the backpack for saving
    local equippedTools = {}
    for _, item in ipairs(character:GetChildren()) do
        if item:IsA("Tool") then
            table.insert(equippedTools, item)
            item.Parent = backpack
        end
    end

    local dataKey = 'key_' .. player.UserId
    local data = PlayerData[player]

    local success, result = pcall(function()
        ItemStore:SetAsync(dataKey, data, {player.UserId})
    end)

    if not success then
        error(result)
    else
        warn('Successfully saved', player, 'items to Datastore')
    end

    -- Move equipped tools back to the character
    for _, tool in ipairs(equippedTools) do
        tool.Parent = character
    end
end

do smth like

for i, v in pairs(serverstorage.tools:GetChildren()) do
if player:FindFirstChild(v.Name) then
--- basically looks for any tools in the Player's model in workspace and sees if it has any name of the tools in the tool folder
end
end

or

for i, v in pairs(Player:GetChildren()) do
if v:IsA("Tool") then
-- checks if there is any Tools equipped in the Player model, and if is, add it to the table of datastore
end
end

Didn’t seem to work, no errors in the output either. Now the datastore doesn’t save at all. Sorry man, this whole datastore thing is new to me and also weird. I appreciate you trying to help me though.

I feel like this would work but I don’t know where to add this in the script. This script isn’t mine and I don’t know where in the script it gets the player’s items and saves them to the table.

K let’s address the potential issue of the ItemStore not being defined in the snippet you provided. Ensure you have initialized ItemStore correctly at the beginning of your script using the DataStoreService

-- Assuming ItemStore is correctly initialized earlier in your script
-- local DataStoreService = game:GetService("DataStoreService")
-- local ItemStore = DataStoreService:GetDataStore("YourDataStoreName")

local function Save(player)
    local character = player.Character or player.CharacterAdded:Wait()
    local backpack = player:FindFirstChild("Backpack")
    if not backpack then
        warn("Backpack not found for", player.Name)
        return
    end

    -- Temporarily move equipped tools to the backpack for saving
    local equippedTools = {}
    for _, item in ipairs(character:GetChildren()) do
        if item:IsA("Tool") then
            table.insert(equippedTools, item)
            item.Parent = backpack
        end
    end

    local dataKey = 'key_' .. player.UserId
    -- Ensure PlayerData is properly initialized and contains the data for this player
    local data = PlayerData[player.UserId] -- Assuming PlayerData is indexed by UserId

    -- Make sure 'data' is not nil or empty before attempting to save
    if not data or next(data) == nil then
        warn("No data to save for", player.Name)
        return
    end

    local success, result = pcall(function()
        ItemStore:SetAsync(dataKey, data)
    end)

    if not success then
        warn("Failed to save data for", player.Name, "-", result)
    else
        print('Successfully saved', player.Name, 'items to Datastore')
    end

    -- Move equipped tools back to the character
    for _, tool in ipairs(equippedTools) do
        tool.Parent = character
    end
end

I have ItemStore defined in the top of my script, it is assigned to my item datastore

Refined this way try it:

-- Assuming ItemStore is correctly initialized earlier in your script
-- local DataStoreService = game:GetService("DataStoreService")
-- local ItemStore = DataStoreService:GetDataStore("YourDataStoreName")

local function Save(player)
    -- Wait for the character to load to ensure all tools can be accounted for.
    local character = player.Character or player.CharacterAdded:Wait()
    local backpack = player:FindFirstChild("Backpack")
    if not backpack then
        warn("Backpack not found for", player.Name)
        return
    end

    -- Temporarily move equipped tools to the backpack for saving
    local equippedTools = {}
    for _, item in ipairs(character:GetChildren()) do
        if item:IsA("Tool") then
            table.insert(equippedTools, item)
            -- Moving equipped tools to the backpack to ensure they are saved.
            item.Parent = backpack
        end
    end

    local dataKey = 'key_' .. player.UserId
    -- Ensure PlayerData is properly initialized and contains the data for this player
    -- Assuming PlayerData is a table indexed by UserId with relevant player data.
    local data = PlayerData[player.UserId]

    -- Make sure 'data' is not nil or empty before attempting to save
    if not data or next(data) == nil then
        warn("No data to save for", player.Name)
        return
    end

    -- Using pcall to safely attempt to save data to the DataStore
    local success, result = pcall(function()
        ItemStore:SetAsync(dataKey, data)
    end)

    if not success then
        warn("Failed to save data for", player.Name, "-", result)
    else
        print('Successfully saved', player.Name, 'items to Datastore')
    end

    -- Move equipped tools back to the character
    for _, tool in ipairs(equippedTools) do
        -- It's a good practice to ensure the character still exists before moving items back.
        if character and character.Parent then
            tool.Parent = character
        end
    end
end

Tried this but it did not work. Items don’t save at all now

The item saving script completely works and saves all items but not the ones that are equipped when you die or leave the game. I would probably need to find a way to save the items in the player’s character when the player leaves or dies instead of moving the items.

Updated with the equipped and leaving handling effects to save

local DataStoreService = game:GetService("DataStoreService")
local ItemStore = DataStoreService:GetDataStore("YourDataStoreName")

local function GetItemsToSave(player)
    local itemsToSave = {}

    -- Get items from Backpack
    local backpack = player:FindFirstChild("Backpack")
    if backpack then
        for _, item in ipairs(backpack:GetChildren()) do
            if item:IsA("Tool") then
                table.insert(itemsToSave, item.Name)
            end
        end
    end

    -- Get equipped items from Character
    local character = player.Character or player.CharacterAdded:Wait()
    for _, item in ipairs(character:GetChildren()) do
        if item:IsA("Tool") then
            table.insert(itemsToSave, item.Name)
        end
    end

    return itemsToSave
end

local function SaveItems(player, itemsToSave)
    local dataKey = 'key_' .. player.UserId
    -- Using pcall to safely attempt to save the items list to the DataStore
    local success, result = pcall(function()
        ItemStore:SetAsync(dataKey, itemsToSave)
    end)

    if not success then
        warn("Failed to save data for", player.Name, "-", result)
    else
        print('Successfully saved', player.Name, "'s items to Datastore")
    end
end

local function Save(player)
    local itemsToSave = GetItemsToSave(player)
    SaveItems(player, itemsToSave)
end

-- Hook into player leaving and character death to trigger save
game.Players.PlayerRemoving:Connect(Save)
game.Players.PlayerAdded:Connect(function(player)
    player.CharacterAdded:Connect(function(character)
        character.Humanoid.Died:Connect(function()
            Save(player)
        end)
    end)
end)

Doesn’t seem to work, doesn’t save items at all anymore.

We will try now these steps

local DataStoreService = game:GetService("DataStoreService")
local ItemStore = DataStoreService:GetDataStore("YourDataStoreName")

local function GetItemsToSave(player)
    local itemsToSave = {}

    -- Function to add items from a container (Backpack or Character)
    local function addItemsFromContainer(container)
        for _, item in ipairs(container:GetChildren()) do
            if item:IsA("Tool") then
                table.insert(itemsToSave, item.Name)
            end
        end
    end

    -- Get items from Backpack
    local backpack = player:FindFirstChild("Backpack")
    if backpack then
        addItemsFromContainer(backpack)
    end

    -- Get equipped items from Character
    local character = player.Character or player.CharacterAdded:Wait()
    addItemsFromContainer(character)

    return itemsToSave
end

local function SaveItems(player, itemsToSave)
    local dataKey = 'key_' .. player.UserId
    local success, result = pcall(function()
        ItemStore:SetAsync(dataKey, itemsToSave)
    end)

    if not success then
        warn("Failed to save data for", player.Name, "-", result)
    else
        print('Successfully saved', player.Name, "'s items to Datastore")
    end
end

local function Save(player)
    local itemsToSave = GetItemsToSave(player)
    SaveItems(player, itemsToSave)
end

local function SetupPlayer(player)
    local function onItemChanged()
        Save(player)
    end

    -- Connect events for Backpack and Character
    local backpack = player:FindFirstChild("Backpack") or player:WaitForChild("Backpack")
    backpack.ChildAdded:Connect(onItemChanged)
    backpack.ChildRemoved:Connect(onItemChanged)

    player.CharacterAdded:Connect(function(character)
        character.Humanoid.Died:Connect(function()
            Save(player)
        end)
        character.ChildAdded:Connect(onItemChanged)
        character.ChildRemoved:Connect(onItemChanged)
    end)
end

-- Hook into player events
game.Players.PlayerRemoving:Connect(Save)
game.Players.PlayerAdded:Connect(function(player)
    SetupPlayer(player)
end)


I tried this and it didn’t seem to work either, items still don’t save and this error comes up in the output. The script is below:

local folders_to_save = {

	-- 'Backpack' is the name of player's folder where items are stored
	-- And Items are the folder for where the items are originated

	['Backpack'] = game.ServerStorage.Items
}

-- Reload the saved items every time player respawns
local reload_items_on_reset = true

local DataStoreService = game:GetService("DataStoreService")
local ItemStore = DataStoreService:GetDataStore("TEST3")

-- This is where we store all the loaded data's
local PlayerData = {}

local function LoadItemsFromData(player: Player, data, onReset: boolean)
	local folders = {}

	for storeFolderName, itemsFolder in pairs(folders_to_save) do
		local folder = player:FindFirstChild(storeFolderName)
		if not folder then
			-- the folder does not exist, so we create it
			folder = Instance.new("Folder")
			folder.Name = storeFolderName
			folder.Parent = player
		end
		-- keeping track of the folder
		folders[storeFolderName] = folder
	end

	-- now we're going to make a function to add items in data
	local function AddItem(item: Instance, folder: Folder, index: number)

		-- the data doesn't have the directory for the folder
		if not data[folder.Name] then
			-- we create it
			data[folder.Name] = {}
		end

		-- if the item wasn't exist in data
		if not index then
			-- getting the index of next to the very last index
			index = #data[folder.Name] + 1
			-- inserting the item name to data
			table.insert(data[folder.Name], index, item.Name)
		end


		-- detecting item parent change
		item.AncestryChanged:Connect(function(_, newParent)
			-- if item is not in the folder anymore
			-- and its not because player is resetting
			if newParent ~= folder and folder.Parent ~= nil then
				data[folder.Name][index] = nil
			end
		end)
	end

	-- iterating every item directory of the data
	for storeFolderName, savedItems in pairs(data) do

		-- if player is respawning, and folder is not Backpack
		-- we cancel the iteration
		--
		-- this is because only Backpack is being resetted
		-- after player respawn
		--
		-- other folder doesnt
		-- (btw this script supports not only backpack to save)
		-- (it also supports saving other kind of folders)
		-- (as long it is inside player)
		if onReset == true and storeFolderName ~= 'Backpack' then
			continue
		end


		local itemsFolder: Folder = folders_to_save[storeFolderName]

		-- checking if the directory has the items folder
		-- (where the items originated)
		if itemsFolder then

			-- getting the folder from player
			local folder = folders[storeFolderName]

			for index, itemName in pairs(savedItems) do
				-- checking if theres an item in the original items folder
				local item = itemsFolder:FindFirstChild(itemName)
				if item then
					-- cloning the item and put it the player's folder
					local playerItem = item:Clone()
					playerItem.Parent = folder

					-- since the item is exist in data, and has an index
					-- we pass that index in the parameter. and we will modify
					-- the additem function again
					AddItem(playerItem, folder, index)
				else
					-- if the item is not valid in the items folder
					warn(player, 'has unknown item that is said to be in folder', storeFolderName, ":", itemName)
				end
			end

		else
			warn(player, 'has unknown directory saved in data:', storeFolderName)
		end
	end

	-- now we loaded saved items to player's folder
	-- next is we detect of new items added in player folders

	for storeFolderName, folder in pairs(folders) do
		-- we dont need to track the folder anymore
		folders[storeFolderName] = nil

		-- we also need this here
		-- so the item added detector dont run twice
		if onReset == true and storeFolderName ~= 'Backpack' then
			continue
		end

		folder.ChildAdded:Connect(function(item)
			-- we dont have an index, so we leave it empty
			-- it means that the item will be added in data
			-- if it doesnt have an index
			AddItem(item, folder)
		end)
	end
end

-- a function to load player's data
local function Load(player: Player)

	-- if player's data is already loaded, cancel the function
	if PlayerData[player] then
		return warn(player, 'data is already loaded')
	end

	-- The key to access player's data
	local dataKey = 'key_' .. player.UserId

	-- always use pcall for async functions
	local loadedData = nil
	local success, result = pcall(function()
		-- getting the data from ItemStore Datastore
		loadedData = ItemStore:GetAsync(dataKey)
	end)

	-- error occured when loading data, and logging that error in the output
	if not success then
		error(success)
	end

	-- if player is new to the game, they dont have a saved data so its nil
	if loadedData == nil then
		loadedData = {} -- we give it empty data
	end

	warn(player, 'items have been loaded')

	return loadedData
end

--------------------p--0--------------

local function GetItemsToSave(player)
	local itemsToSave = {}

	-- Function to add items from a container (Backpack or Character)
	local function addItemsFromContainer(container)
		for _, item in ipairs(container:GetChildren()) do
			if item:IsA("Tool") then
				table.insert(itemsToSave, item.Name)
			end
		end
	end

	-- Get items from Backpack
	local backpack = player:FindFirstChild("Backpack")
	if backpack then
		addItemsFromContainer(backpack)
	end

	-- Get equipped items from Character
	local character = player.Character or player.CharacterAdded:Wait()
	addItemsFromContainer(character)

	return itemsToSave
end

local function SaveItems(player, itemsToSave)
	local dataKey = 'key_' .. player.UserId
	local success, result = pcall(function()
		ItemStore:SetAsync(dataKey, itemsToSave)
	end)

	if not success then
		warn("Failed to save data for", player.Name, "-", result)
	else
		print('Successfully saved', player.Name, "'s items to Datastore")
	end
end

local function Save(player)
	local itemsToSave = GetItemsToSave(player)
	SaveItems(player, itemsToSave)
end

local function SetupPlayer(player)
	local function onItemChanged()
		Save(player)
	end

	-- Connect events for Backpack and Character
	local backpack = player:FindFirstChild("Backpack") or player:WaitForChild("Backpack")
	backpack.ChildAdded:Connect(onItemChanged)
	backpack.ChildRemoved:Connect(onItemChanged)

	player.CharacterAdded:Connect(function(character)
		character.Humanoid.Died:Connect(function()
			Save(player)
		end)
		character.ChildAdded:Connect(onItemChanged)
		character.ChildRemoved:Connect(onItemChanged)
	end)
end

------------------------------------------

-- handling joining players
game.Players.PlayerAdded:Connect(function(player: Player)
	-- loading the data
	local data = Load(player)
	-- keep track of the data in PlayerData
	PlayerData[player] = data

	-- now we use the LoadItemsFromData function here
	-- waiting until character is loaded
	local character = player.Character or player.CharacterAdded:Wait()
	LoadItemsFromData(player, data)

	if reload_items_on_reset == true then
		player.CharacterAdded:Connect(function(character: Model)
			-- we pass true here to tell that the character respawned
			-- so we going to modify the LoadItemsFromData function
			LoadItemsFromData(player, data, true)
		end)    
	end
end)

game.Players.PlayerRemoving:Connect(function(player: Player)
	Save(player)

	-- player is leaving, so we dont need their data anymore
	-- get rid of it to prevent memory leak

	if PlayerData[player] then
		table.clear(PlayerData[player])
	end

	PlayerData[player] = nil
end)

-- at very last
game:BindToClose(function()
	-- if the game is closing, we will force save all player data
	for _, player in pairs(game.Players:GetPlayers()) do
		Save(player)
	end
end)

-- Hook into player events
game.Players.PlayerRemoving:Connect(Save)
game.Players.PlayerAdded:Connect(function(player)
	SetupPlayer(player)
end)

Having the script with specific error handling more

Improved error handling and many more here

local folders_to_save = {
    ['Backpack'] = game.ServerStorage.Items
}

local reload_items_on_reset = true
local DataStoreService = game:GetService("DataStoreService")
local ItemStore = DataStoreService:GetDataStore("TEST3")
local PlayerData = {}

local function LoadItemsFromData(player, data, onReset)
    local folders = {}

    for storeFolderName, itemsFolder in pairs(folders_to_save) do
        local folder = player:FindFirstChild(storeFolderName)
        if not folder then
            folder = Instance.new("Folder")
            folder.Name = storeFolderName
            folder.Parent = player
        end
        folders[storeFolderName] = folder
    end

    local function AddItem(item, folder, index)
        if not data[folder.Name] then
            data[folder.Name] = {}
        end

        if not index then
            index = #data[folder.Name] + 1
        end
        data[folder.Name][index] = item.Name

        item.AncestryChanged:Connect(function(_, newParent)
            if newParent ~= folder and folder.Parent ~= nil then
                data[folder.Name][index] = nil
            end
        end)
    end

    for storeFolderName, savedItems in pairs(data) do
        if onReset == true and storeFolderName ~= 'Backpack' then
            continue
        end

        local itemsFolder = folders_to_save[storeFolderName]
        if itemsFolder then
            local folder = folders[storeFolderName]
            for index, itemName in pairs(savedItems) do
                local item = itemsFolder:FindFirstChild(itemName)
                if item then
                    local playerItem = item:Clone()
                    playerItem.Parent = folder
                    AddItem(playerItem, folder, index)
                else
                    warn(player, 'has unknown item that is said to be in folder', storeFolderName, ":", itemName)
                end
            end
        else
            warn(player, 'has unknown directory saved in data:', storeFolderName)
        end
    end

    for storeFolderName, folder in pairs(folders) do
        if onReset == true and storeFolderName ~= 'Backpack' then
            continue
        end

        folder.ChildAdded:Connect(function(item)
            if item:IsA("Tool") then
                AddItem(item, folder)
            end
        end)
    end
end

local function Load(player)
    if PlayerData[player] then
        return warn(player, 'data is already loaded')
    end

    local dataKey = 'key_' .. player.UserId
    local success, result = pcall(function()
        return ItemStore:GetAsync(dataKey)
    end)

    if not success then
        warn("Failed to load data for", player.Name, "-", result)
        return {}
    end

    warn(player, 'items have been loaded')
    return result or {}
end

local function GetItemsToSave(player)
    local itemsToSave = {}
    local function addItemsFromContainer(container)
        for _, item in ipairs(container:GetChildren()) do
            if item:IsA("Tool") then
                table.insert(itemsToSave, item.Name)
            end
        end
    end

    local backpack = player:FindFirstChild("Backpack")
    if backpack then
        addItemsFromContainer(backpack)
    end

    local character = player.Character or player.CharacterAdded:Wait()
    addItemsFromContainer(character)
    return itemsToSave
end

local function SaveItems(player, itemsToSave)
    local dataKey = 'key_' .. player.UserId
    local success, result = pcall(function()
        ItemStore:SetAsync(dataKey, itemsToSave)
    end)

    if not success then
        warn("Failed to save data for", player.Name, "-", result)
    else
        print('Successfully saved', player.Name, "'s items to Datastore")
    end
end

local function Save(player)
    local itemsToSave = GetItemsToSave(player)
    SaveItems(player, itemsToSave)
end

local function SetupPlayer(player)
    local function onItemChanged()
        Save(player)
    end

    local backpack = player:FindFirstChild("Backpack") or player:WaitForChild("Backpack")
    backpack.ChildAdded:Connect(onItemChanged)
    backpack.ChildRemoved:Connect(onItemChanged)

    player.CharacterAdded:Connect(function(character)
        character.Humanoid.Died:Connect(function()
            Save(player)
        end)
        character.ChildAdded:Connect(onItemChanged)
        character.ChildRemoved:Connect(onItemChanged)
    end)
end

game.Players.PlayerAdded:Connect(function(player)
    local data = Load(player)
    PlayerData[player] = data
    local character = player.Character or player.CharacterAdded:Wait()
    LoadItemsFromData(player, data)

    if reload_items_on_reset then
        player.CharacterAdded:Connect(function()
            LoadItemsFromData(player, data, true)
        end)    
    end
end)

game.Players.PlayerRemoving:Connect(function(player)
    Save(player)
    if PlayerData[player] then
        table.clear(PlayerData[player])
    end
    PlayerData[player] = nil
end)

game:BindToClose(function()
    for _, player in pairs(game.Players:GetPlayers()) do
        Save(player)
    end
end)

game.Players.PlayerRemoving:Connect(Save)
game.Players.PlayerAdded:Connect(SetupPlayer)

Still doesn’t seem to work and items don’t save

Ok let’s see try providing the error and give a detailed response of why your script is not working or what’s not working in part of the script and have you tried setting up your games mechanics perfectly or organized CORRECTLY to be with the script or pertaining to. Data Stores?

Nevermind, I fixed it using Profile Service. Thank you for trying to help me though, I appreciate it.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.