How to save tools with ProfileService?

Well, I am trying to save the tools (apparently if they are saved) and load the tools, apparently I get an error when trying to get the names of the tools and I do not know the problem

local function GetTools(player, profile)
	if profile.Data.Tools ~= nil then
		for _, Tools in pairs(profile.Data.Tools) do--Here I get the error, an "pairs"
			if not toolsFolder:FindFirstChild(Tools) then continue end
			local Tool = toolsFolder[Tools]:Clone()
			Tool.Parent = player:WaitForChild("Backpack")
			local ToolGear = toolsFolder[Tools]:Clone()
			ToolGear.Parent = player:WaitForChild("StarterGear")
		end
	end
end

Players.PlayerAdded:Connect(function(player)
	local Profile = DataManager:Get(player, true)
	if not Profile then
		repeat task.wait(0.1)
			Profile = DataManager:Get(player, true)
		until Profile or (not player.Parent)
	end
	if Profile then
		GetTools(player, Profile)
		player:WaitForChild("Backpack").ChildAdded:Connect(function()
			for _, GetTools in pairs(player:WaitForChild("Backpack"):GetChildren()) do
				table.insert(Profile.Data.Tools, GetTools.Name)
			end
		end)
	end
end)

These are the ProfileService data:

local Players = game:GetService("Players")
local ProfileService = require(script.ProfileService)

local saveStructure = {
Tools = {};
Money = 0;
LogInTimes = 0;
LogInGiift = 0;
}
2 Likes

Could you please give us the error

try “in ipairs” not sure what profile.Data.Tools is an array or table.

https://education.roblox.com/en-us/resources/pairs-and-ipairs-intro

1 Like

I’ve already tried that, however it doesn’t work for me.

This is the error that gives me:
invalid argument #1 to 'pairs' (table expected, got string)

This is a table:

Can you show us the code where you update Profile.Data.Tools? My best guess is you’re overriding it with the actual tool name instead of indexing/inserting the tool name into the array.

This is what updates it:

or do you mean the whole script that gets the data from the ProfileService?

Here is all about the ProfileService data
local Players = game:GetService("Players") 
local ProfileService = require(script.ProfileService)
local saveStructure = {
	Tools = {};
	Money = 0;
	LogInTimes = 0;
	LogInGiift = 0;
	
	Shadows = "Medio";
	Water = "Medio";
	Tree = "Enabled";
	
	FPS = "UnEnabled";
	Ping = "UnEnabledPing";
	BrilloVol = 0.7;
	PlayerChose = "ForLocalPlayer";
	Language = "English";
	SlotsInventory = 90;
	
	Crouch = "Keep";
	Sprint = "Keep";
}

local PlayerProfileStore = ProfileService.GetProfileStore("test14", saveStructure)

local cachedProfiles = {}

local function DoSomethingWithALoadedProfile(player, profile)
	local GiftMoney = math.random(100, 270)
	profile.Data.LogInTimes = profile.Data.LogInTimes + 1
	profile.Data.LogInGiift = profile.Data.LogInGiift + 1
	print(player.Name, " has logged in " .. tostring(profile.Data.LogInTimes)..	" time" .. ((profile.Data.LogInTimes > 1) and "s" or ""))
	if profile.Data.LogInGiift >= 120 then
		profile.Data.Money = profile.Data.Money + GiftMoney
		print(player.Name, "has been given a gift of $".. GiftMoney.. ".", "Actualmente tiene $".. profile.Data.Money.. ".")
		profile.Data.LogInGiift = 0
	else
		print(player.Name .. " owns " .. tostring(profile.Data.Money) .. " now!")
	end
end

local function PlayerAdded(player)
	local profile = PlayerProfileStore:LoadProfileAsync("Player_".. player.UserId, "ForceLoad")
	if profile ~= nil then
        profile:Reconcile()
		profile:ListenToRelease(function()
			cachedProfiles[player] = nil
			player:Kick("Tus datos no han sido cargados. Por favor únase nuevamente")
		end)
		if player:IsDescendantOf(Players) then
			cachedProfiles[player] = profile
			DoSomethingWithALoadedProfile(player, profile)
		else
			profile:Release()
		end
	else
		player:Kick("No se pueden cargar tus datos. Por favor únase nuevamente")
	end
end

for _, player in ipairs(Players:GetPlayers()) do
	coroutine.wrap(PlayerAdded)(player)
end

local function PlayerRemoving(player)
	local profile = cachedProfiles[player]
	if profile ~= nil then
		profile:Release()
	end
end

Players.PlayerAdded:Connect(PlayerAdded)
Players.PlayerRemoving:Connect(PlayerRemoving)

function cachedProfiles:Get(player, yield)
	local profile = cachedProfiles[player]
	if yield and not profile then
		repeat task.wait(0.1)
			profile = cachedProfiles[player]
		until profile or (not player.Parent)
	end
	if profile then
		return profile
	end
end

return cachedProfiles

I think this is how the data is updated

I mean when the player buys or is given a tool, that code might be updating Profile.Data.Tools to be a string (the tool name) instead of it being an array.

Also, change:
for _, GetTools in pairs(player:WaitForChild("Backpack"):GetChildren()) do

To
for _, Tool in pairs(player:WaitForChild("Backpack"):GetChildren()) do

I don’t think this is directly causing the error ^ but the loop might think GetTools.Name is referencing the function. You’d have to change GetTools.Name to Tool.Name too.

I certainly didn’t think that. well it keeps giving me the error

ah ya, ya. I changed the:

for another and it started working, although now, I have another problem loading the tools …

And it is that if there is a tool and it saves it and later loads it, there will be more than one tool

Yeah but it also helps to not name variables the same as functions, it’s confusing to read sometimes. I think somewhere in your code you have:

Profile.Data.Tools = Tool.Name or something of the sort.

Ctrl + Shift + F (Find All) then type Profile.Data.Tools = to try and find it

Actually no, at the time I thought about putting that, but then I thought that I would only put a variable from the tool. So in the end I put table.insert

You could try saving a boolean, if this Value is true then it would give the tool to the player.

Why not just use the new DataStoreV2? Didn’t it receive some updates that made it more reliable? I don’t know much about ProfileService that much, but I’ve been able to keep my DataStores perfectly fine, so far I haven’t been reported of any data loss since DataStoreV2. (I’m not talking about the DataStore2 module, I’m talking about roblox’s official DataStoreV2)

I decided to use Profile Service because I tried to find the how to use DataStore v2 and I did not find anything

DataStoreV2 isn’t anything different from DataStore2, all they did was introduce new features like Tagging, and some other things I honestly forgot.

It’s just your same old DataStore Roblox system, but more reliable by the seems.

It still uses the old DataStore:SetAsync(), DataStore:RemoveAsync(), and DataStore:UpdateAsync() functions.

From what I have seen, there is no script that contains that. Well, now I have another problem, and it is that I already mentioned it before “if there is only one tool and it is saved, when you enter the game again, you will have more tools of the same”

Because you’re doing table.insert when the player loads their data. ProfileService already has your array of tools saved, so when the player joins and you add that tool name (from their backpack in the loop) to the array, you’re duplicating their items.

Ah, it is true, I will change it in a moment. Sorry, I speak another language so I have a hard time structuring the word