You could try this. I added some code to check if there is a tool in the player’s character, if there is then it saves that too.
local DataStore = game:GetService("DataStoreService"):GetDataStore("MyDataStore")
game.Players.PlayerAdded:Connect(function(plr)
local data
local success, errorMessage = pcall(function()
data = DataStore:GetAsync(plr.UserId)
end)
if data ~= nil then
for _, toolName in pairs(data) do
local tool = game.ReplicatedStorage.ToolsSaved:FindFirstChild(toolName)
if tool then
local newTool = tool:Clone()
newTool.Parent = plr.Backpack
local newTool = tool:Clone()
newTool.Parent = plr.StarterGear
end
end
end
end)
game.Players.PlayerRemoving:Connect(function(plr)
local toolsTable = {}
for _, tool in pairs(plr.Backpack:GetChildren()) do
if game.ReplicatedStorage.ToolsSaved:FindFirstChild(tool.Name) then
table.insert(toolsTable,tool.Name)
end
end
local toolcheck = plr.Character:FindFirstChildWhichIsA("Tool")
if toolcheck then
table.insert(toolsTable,toolcheck.Name)
end
local success, errorMessage = pcall(function()
DataStore:SetAsync(plr.UserId,toolsTable)
end)
end)
game:BindToClose(function()
for _, plr in pairs(game.Players:GetPlayers()) do
local toolsTable = {}
for _, tool in pairs(plr.StarterGear:GetChildren()) do
if game.ReplicatedStorage.ToolsSaved:FindFirstChild(tool.Name) then
table.insert(toolsTable,tool.Name)
end
end
local success, errorMessage = pcall(function()
DataStore:SetAsync(plr.UserId,toolsTable)
end)
end
end)
while wait(10) do --Every 30 seconds loop through all of the players (you can also change this time to anything you want)
for i, plr in pairs (game.Players:GetChildren()) do --loop through all of the players
local toolsTable = {}
for _, tool in pairs(plr.StarterGear:GetChildren()) do
if game.ReplicatedStorage.ToolsSaved:FindFirstChild(tool.Name) then
table.insert(toolsTable,tool.Name)
end
end
local success, errorMessage = pcall(function()
DataStore:SetAsync(plr.UserId,toolsTable)
end)
end
end
The others are correct about equipped tools being lost. If the tool is equipped it is taken from the backpack and put into the character (A Descendant of workspace).
A fix for this would be to add in any tools inside the character into the table you are saving.
local Tools = {}
local SearchChar = Player.Character:GetDescendants()
for i = 1,#SearchChar do
if SearchChar.ClassName == "tool" then
table.insert(Tools,SearchChar[i].Name)
end
end
I strongly recommend splitting up your data persistence code into modules for saving/loading. Not doing so can make the whole thing difficult to edit and maintain. Second off, you should have pcalls retry themself if they don’t succeed. My current solution is having a set wait time, attempting the pcall, and if it fails, double the wait time and repeat. There are other things you may want to consider like making it stop retrying after a certain amount of tries, but that’s up to you.
Second, I don’t recommend using StarterGear as a spot to save things, this will create issues if the player leaves and you’re trying to save the data, the tools could get cleaned up by the time you’re saving it. Store any critical player info in a folder in ReplicatedStorage (or ServerStorage) instead so you don’t have to worry about that, and refer to it in other scripts like so.
Ooh, yeah. I was the one who suggested it, he was using Backpack which was much worse. So yeah, having that somewhere in ServerStorage, pretty good idea. Everytime a new child gets added probs.
Before any request to the data store you should do:
Example:
local sucess, errorMsg = pcall(function()
playerData = ds:GetAsync(plr.UserId)
end)
if not sucess and errorMsg then
--if the script didn't work and if there was an error then
warn(errorMsg)
end
Sucess (first argument) would be a bool value, if it is true, the script went fine. If it’s false then something’s wrong.
errorMsg (second argument) will be usually a string contains info about any errors that happened in that function. Another thing you should be careful with, is that if you return anything inside this function, errorMsg gets set to that.
This method of pcalls is used to make it so that the script still works if there’s a problem retrieving info for example.