Well, I already have the script that saves the tools and the StringValue values that are in each tool, the problem is that the tools that are repeated are not saved, only one is saved if there are already several repeated tools, so that’s why I come to ask for help. I’ve already tried to save everything but my scriptin level is barely medium (and they helped me with the code), but I just can’t get all the tools to save (even the repeated ones), it helps…
local dss = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local toolsDS = dss:GetDataStore("ToolDataPlayer")
local ServerStorage = game:GetService("ServerStorage")
local toolsFolder = ServerStorage.ToolsFolder
Players.PlayerAdded:Connect(function(plr)
local OwnedTools = toolsDS:GetAsync(plr.UserId) or {}
for toolname, propiedades in pairs(OwnedTools) do
local Tool = toolsFolder[toolname]:Clone()
Tool.Stack.Value = propiedades["Stacks"]
Tool.Parent = plr.Backpack
local ToolGear = toolsFolder[toolname]:Clone()
Tool.Stack.Value = propiedades["Stacks"]
Tool.Parent = plr.StarterGear
end
plr.CharacterRemoving:Connect(function(char)
char.Humanoid:UnequipTools()
end)
end)
Players.PlayerRemoving:Connect(function(plr)
local OwnedTools = { }
for i, toolInBackpack in pairs(plr.Backpack:GetChildren()) do
if not toolInBackpack:IsA("Tool") then return end
OwnedTools[toolInBackpack.Name] = {
["Stacks"] = toolInBackpack.Stack.Value;
}
end
local success, errormsg = pcall(function()
toolsDS:SetAsync(plr.UserId, OwnedTools)
end)
if errormsg then
warn(errormsg)
end
end)
This happens when you use a dictionary. When you have multiple entities of the same name and you set the index in the table it will overwrite with the latest one. You should be using arrays instead if you want to have multiple elements of the same name in your table.
The tool data can be a dictionary but the overall table needs to be an array. For the saving portion, you can compose a new table with the name and the stacks as you go through the backpack:
-- Shouldn't assume Backpack exists
for _, tool in ipairs(plr.Backpack:GetChildren()) do
-- Use continue to skip the iteration. Return will stop the collection
-- of tools if a non-Tool is in the Backpack, leading to potentially
-- unpredictable behaviour (data loss) when saving.
if not tool:IsA("Tool") then continue end
-- OwnedTools is now an array containing dictionaries of tool names and
-- their respective stacks values.
table.insert(OwnedTools, {ToolName = tool.Name, Stacks = tool.Stack.Value})
end
As for when you’re loading them back out, you just need to change how you treat the returned data in terms of an array instead of a dictionary.
for _, toolData in ipairs(OwnedTools) do
-- Don't assume that your items exist!
if not ToolsFolder:FindFirstChild(toolData.ToolName) then continue end
local tool = ToolsFolder[toolData.ToolName]:Clone()
-- Set your stacks value and then the parent
end
This isn’t a drop-in fix and just provides guidelines so make sure you’re using this to understand how you might be able to tackle the problem rather than expecting this to fix your problem with just a simple copy-and-paste. If you don’t understand the logic flow here though, I can help with that.
Some general tips with that out of the way though:
If you’re intending to save more than just tool data, make sure you put everything into one DataStore rather than multiple. I don’t know the extent of your data saving but I’m just making the assumption that you’d use a new DataStore for other data (e.g. currency) down the line since the information (name) of your DataStore is uniquely tailored to tools. Always try to use as few DataStores as possible.
pcall DataStore calls, always. Your current pattern may cause data loss or break systems if there’s a DataStore outage because you’re not handling cases of errors. If a DataStore outage occurs, you replace the player’s data with a blank-constructed table meaning they will lose everything from there on and there’s no way to cancel the save that’ll happen when they leave.
In a serious project, you’ll want to aim to divorce your data saving from entropic instances of the player - that meaning whatever’s in their backpack or character. Data saving should remain purely data with the server actively tracking inventory and/or stats for the player and then game systems accordingly grant items to the player based on that data. Your source of truth should be an internal cache rather than the player’s inventory which can change on the fly.
Yes, I know, I was looking for tutorials to save the data and I just thought something was wrong. I’m still getting into the advanced stuff, so thanks.
Edit: I use other dataStore for other things that have nothing to do with the tools, because it is as you mentioned, it is not a solution because it does not save the tools, I will see how to fix it (if I can).
Edit2: ah ya, I already saved at least once and did not notice that the tool and the value of stringValue were loaded with the same input (“ToolName”).
Edit3: Although it still does not save well, I’ll see what I can do.
Edit4: Well, I came up with an idea that does not seem to me but it is the most feasible: That the same player saves his data with a RemoteEvent.
I don’t know, I guess I was able to get the data to save without any glitch (probably no idea) by removing the “or {}” part. Now it is able to save, however, I still have the problem that the repeated tools are not saved and I honestly have no idea how to make the repeated tools save with their respective values