Saving Backpack Data

I am trying to make a system in which when you leave the game, the tools in your Backpack save. Now everything is going well except there is one problem, it is sometimes saving the data, well to an extent. The data is saving properly, but it isn’t transferring the tools to the player’s backpack, it sometimes does and sometimes doesn’t which causes players to lose their data.

I am using ProfileService for saving the data and I’m new to it as well so if anybody is experienced with data saving or the module, please help me out on this.

Script:

-- ProfileTemplate table is what empty profiles will default to.
-- Updating the template will not include missing template values
--   in existing player profiles!
local ProfileTemplate = {
	Items = {},
	LogInTimes = 0
}

-----
----- Loaded Modules 

local ProfileService = require(game.ServerScriptService.Modules.ProfileService)

----- Private Variables -----

local Players = game:GetService("Players")

local ProfileStore = ProfileService.GetProfileStore(
	"PlayerData",
	ProfileTemplate
)

local Profiles = {} -- [player] = profile

----- Private Functions -----

local function GiveItems(profile, player)
	-- If "Cash" was not defined in the ProfileTemplate at game launch,
	--   you will have to perform the following:
	local ItemCount = profile.Data.Items
	
	for i,v in pairs(ItemCount) do
		local tool = workspace.Assets.Tools:FindFirstChild(v)
		
		if (tool) then
			tool:Clone().Parent = player.Backpack
		end
	end
end

local function DoSomethingWithALoadedProfile(player, profile)
	profile.Data.LogInTimes = profile.Data.LogInTimes + 1
	GiveItems(profile, player)
end

local function PlayerAdded(player)
	local profile = ProfileStore:LoadProfileAsync("Player_" .. player.UserId)
	if profile ~= nil then
		profile:AddUserId(player.UserId) -- GDPR compliance
		profile:Reconcile() -- Fill in missing variables from ProfileTemplate (optional)
		profile:ListenToRelease(function()
			Profiles[player] = nil
			-- The profile could've been loaded on another Roblox server:
			player:Kick()
		end)
		if player:IsDescendantOf(Players) == true then
			Profiles[player] = profile
			-- A profile has been successfully loaded:
			DoSomethingWithALoadedProfile(player, profile)
		else
			-- Player left before the profile loaded:
			profile:Release()
		end
	else
		-- The profile couldn't be loaded possibly due to other
		--   Roblox servers trying to load this profile at the same time:
		player:Kick() 
	end
end

----- Initialize -----

-- In case Players have joined the server earlier than this script ran:
for _, player in ipairs(Players:GetPlayers()) do
	task.spawn(PlayerAdded, player)
end

----- Connections -----

Players.PlayerAdded:Connect(PlayerAdded)

Players.PlayerRemoving:Connect(function(player)
	local profile = Profiles[player]
	
	table.clear(profile.Data.Items)
	
	for i,v in pairs(player.Backpack:GetChildren()) do
		table.insert(profile.Data.Items, v.Name)
	end
	
	if profile ~= nil then
		profile:Release()
	end
end)

Focus on the GiveItems function as that is where the problem is arising mainly.

And before you ask, yes everything is loading properly, yes all variables have been defined properly.

To save the data which function are you using? It’s :SetAsync()? Or :UpdateAsync()?

Not sure, ProfileService is doing it all for me. It IS saving the Data though, it just isn’t loading it in properly.

When the player leaves (PlayerRemoving event), the Items array has what kind of data on it, are they numbers, strings, etc.? If possible, could you print the value of Items to the console and post it here.

I’m saving the Item name’s and then cloning the names from a folder into the player’s backpack as you can’t store instances in a table.

The output is this

image

You said that the problem is mainly in the function GiveItems. And also that the concern was loading the data. Something I don’t understand is that, the array of the item’s names are loading however the tools are not being accordingly added to the backpack, or, the item’s names are not loading at all, and it gives you an empty array or nil?

local tool = workspace.Assets.Tools:FindFirstChild(v)

perhaps waitforchild instead? The code looks flawless otherwise.

WaitForChild won’t return nil if the instance isn’t found, it’ll just infinitely yield the script.

we can assume that there will not be a nil instance but perhaps the item in question doesn’t load in quick enough?

if infinite yield detected then something is wrong and it is saving a non-existent item.

if it still doesn’t give all items and no yielding then it is not saving properly.

Well, that’s true. But I’d first have a table with all valid items, then try to get it from the folder.

Sorry for the misunderstanding, the problem is the array of the item’s names are loading however the tools are not being accordingly added to the backpack. I have everything correct, it’s working sometimes, other times it doesn’t work at all. It’s very strange to me

Maybe something like move the giver to characte added wil work?
Something like this

2 Likes

Thank you, I don’t know why the template code doesn’t have that CharacterAdded event. I thought it wasn’t supposed to be there, turns out, it was.