I am attempting to save tools with ProfileService so that if a player leaves and joins back their tools that were in their backpack are saved. Help with this would be appreciated! My ProfileService handler code it down below.
local Players = game:GetService("Players")
local ServerScriptService = game:GetService("ServerScriptService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Modules = ReplicatedStorage.Modules
local Libs = Modules.Libs
local DataSaving = Libs.DataSaving
local Communication = Libs.Communication
local Base = Modules.Base
local Template = require(DataSaving.Template)
local ProfileService = require(DataSaving.ProfileService)
local Inventory = require(Base.InventoryServer)
local Signal = require(Communication.Signal)
local leaderStats = require(DataSaving["LeaderStats/Data"])
local DataHandler = {}
local ProfileStore = ProfileService.GetProfileStore("Data2024", Template)
DataHandler.Profiles = {}
local Profiles = DataHandler.Profiles
function DataHandler.PlayerAdded(player: Player)
local profile = ProfileStore:LoadProfileAsync("Player_" .. player.UserId)
if profile then
profile:AddUserId(player.UserId)
profile:Reconcile()
profile:ListenToRelease(function()
Profiles[player] = nil
player:Kick("Failed to load session data. Please try rejoining after 5-10 minutes.")
end)
if not player:IsDescendantOf(Players) then
profile:Release()
else
Profiles[player] = profile
leaderStats:Create(player, profile)
end
else
player:Kick("Failed to load session data. Please try rejoining after 5-10 minutes.")
end
end
function DataHandler:Init()
for _, player in Players:GetPlayers() do
task.spawn(DataHandler.PlayerAdded, player)
end
Players.PlayerAdded:Connect(DataHandler.PlayerAdded)
Players.PlayerRemoving:Connect(function(player)
if Profiles[player] then
Profiles[player]:Release()
end
end)
end
function DataHandler:GetProfile(player)
assert(Profiles[player], string.format("Profile does not exist for %s", player.UserId))
return Profiles[player]
end
function DataHandler:Get(player, key)
local profile = DataHandler:GetProfile(player)
assert(profile.Data[key], string.format("Data does not exist for key: %s"), key)
return profile.Data[key]
end
function DataHandler:Set(player, key, value)
local profile = DataHandler:GetProfile(player)
assert(profile.Data[key], string.format("Data does not exist for key: %s"), key)
assert(type(profile.Data[key]) == type(value))
profile.Data[key] = value
end
function DataHandler:Update(player, key, callBack)
local profile = DataHandler:GetProfile(player)
local oldData = self:Get(player, key)
local newData = callBack(oldData)
self:Set(player, key, newData)
end
return DataHandler
If you have a folder for the tools then you could just save the names and when the player joins read the names and get the tool from the folder
save code
-- save
local backpack = player.Backpack -- use waitforchild or findfirstchild please
local tools = {}
for i, tool in pairs(backpack:GetChildren()) do
if (tool:IsA("Tool")) then
tools[#tools + 1] = tool.Name
end
end
DataHandler:Set(player, "tools", tools)
Hey! I tried your method but found it hard to work with. Down below is the code I’ve decided to go with. The first codeblock is the DataHandler, and the second is from a second script that handles the Player data inside a PlayerAdded function. Everything is working besides Argument 1 missing or nil - Server - InventoryServer:306 (Line 306 is the following code:
if not toolsFolder:FindFirstChild(ToolsWithStacks.ToolName) then print(“:C”) continue end
)
Being printed on the inventory sometimes and “Nil!” always being printed in the DataHandler. Also, “Done” never gets printed.
function DataHandler:Init()
for _, player in Players:GetPlayers() do
task.spawn(DataHandler.PlayerAdded, player)
end
Players.PlayerAdded:Connect(DataHandler.PlayerAdded)
Players.PlayerRemoving:Connect(function(player)
if Profiles[player] then
local Tools = {}
for _, Tool in pairs (player.Backpack:GetChildren()) do
if Tools[Tool.Name] == nil then
print("Nil!")
Tools[Tool.Name] = Tool.Name
elseif Tools[Tool.Name] ~= nil then
print("Inserting....")
table.insert(Tools, Tool.Name)
end
end
table.clear(Tools)
Profiles[player].Data.Items = Tools
Profiles[player]:Release()
end
end)
end
Second:
local Profile = DataHandler:Get(player, true)
for _, ToolsWithStacks in pairs(Profile.Data.Items) do
if not toolsFolder:FindFirstChild(ToolsWithStacks.ToolName) then print(":C") continue end
for i = 1, #ToolsWithStacks do
print("Done")
local Tool = toolsFolder[ToolsWithStacks.ToolName]:Clone()
Tool.Parent = player:WaitForChild("Backpack")
end
end
for _, Tool in pairs (player.Backpack:GetChildren()) do
if Tools[Tool.Name] == nil then -- table needs to be (not exactly): {["name_of_tool"] = nil} or {}
print("Nil!")
Tools[Tool.Name] = Tool.Name -- table: {["name_of_tool"] = "name_of_tool"}
elseif Tools[Tool.Name] ~= nil then -- table needs to be (not exactly): {["name_of_tool"] = any}
print("Inserting....")
table.insert(Tools, Tool.Name) -- table: {["name_of_tool"] = "name_of_tool", "name_of_tool"}
end
end
also remove the table.clear since it just sets the table to {}.
Hello, thank you for your response; although I am still a bit confused as to what you mean.
I wrote out the following code below:
Players.PlayerRemoving:Connect(function(player)
if Profiles[player] then
local Tools = {}
for _, Tool in pairs(player.Backpack:GetChildren()) do
if Tools{["NameOfTool"] = nil} or {} then -- table needs to be (not exactly): {["name_of_tool"] = nil} or {}
print("Nil!")
Tools{["NameOfTool"] = Tool.Name}
print(Tools)
elseif Tools{["NameOfTool"] = true} then -- table needs to be (not exactly): {["name_of_tool"] = any}
print("Inserting....")
Tools{["NameOfTool"] = "NameOfTool", Tool.Name}
end
end
Profiles[player].Data.Items = Tools
Profiles[player]:Release()
end
end)
end
I have attempted to debug and read docs but they are not of much help.
Players.PlayerRemoving:Connect(function(player)
if Profiles[player] then
local Tools = {}
for _, Tool in pairs(player.Backpack:GetChildren()) do
if not table.find(Tools, Tool.Name, 1) then -- You can keep this away if the player can have the sime tools more than one time
print("Inserting into save")
table.insert(Tools, Tool.Name)
else -- You can keep this away if the player can have the sime tools more than one time
print("Tool is already in the save!")
end
end
Profiles[player].Data.Items = Tools
Profiles[player]:Release()
end
end)
You should think of tables like arrays and dictionaries combined into one data structure
Hey, I updated my codebase to suit your code and changed some things that I may or may not regret changing . Below is my codebase following your changes. For some reason, the "Done" in the server code NEVER gets printed.
[1] The DataSaving Script
[2] The tool Adding Script
[1]:
if Profiles[player] then
local Tools = {ToolsWithStacks = {}}
for _, Tool in pairs(player.Backpack:GetChildren()) do
table.insert(Tools.ToolsWithStacks, {ToolName = Tool.Name})
end
Profiles[player].Data.Items = Tools
Profiles[player]:Release()
end
[2]:
for _, Tools in Profile.Data.Items.ToolsWithStacks do
if not toolsFolder:FindFirstChild(Tools.ToolName) then print(":C") continue end
for i = 1, #Tools do
print("Done")
local Tool = toolsFolder[Tools.ToolName]:Clone()
Tool.Parent = player.Backpack
end
end
end)