so recently i have made a datastore to make a dictionary save, the one dictionary for glove values does save, but the one for the scriptvalues doesnt. for some reason the dictionary says a value but when i save it and then do getasync it just prints out nil, even tough when i run it in a pcall it still says null and it saves, but it just always returns nil on the script datastore
this is my code the formatting glitched out so i will paste it unformatted sorry
local DatastoreService = game:GetService(“DataStoreService”)
local GlovesSave = DatastoreService:GetDataStore(“GloveSave”)
local ScriptSave = DatastoreService:GetDataStore(“ScriptSave”)
local function folderToDictionary(folder)
local dictionary = {}
for _, object in ipairs(folder:GetChildren()) do
if object:IsA("Folder") then
dictionary[object.Name] = folderToDictionary(object)
elseif object:IsA("ValueBase") or object.ClassName:match("Value") then
dictionary[object.Name] = tostring(object.Value)
end
end
return dictionary
end
function GetCode()
local code = math.random(0,999999)
if GlovesSave:GetAsync(code) == nil then
return code
else
return nil
end
end
script.Parent.MouseButton1Click:Connect(function()
local code
repeat code = GetCode() until code ~= nil
script.Parent.Parent.code.Text = code
local plr = game.Players:GetPlayerFromCharacter(script.Parent.Parent.Parent.Parent.Parent.Character)
local dictionary = folderToDictionary(plr.Backpack:GetChildren()[1])
local scriptDictionary = folderToDictionary(plr.Character:WaitForChild("ScriptValues"))
GlovesSave:SetAsync(code,dictionary)
GlovesSave:SetAsync(code,scriptDictionary)
end)
-- Services
local DatastoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
-- DataStores
local GlovesSave = DatastoreService:GetDataStore("GloveSave")
local ScriptSave = DatastoreService:GetDataStore("ScriptSave")
-- Helper Functions
local function folderToDictionary(folder)
local dictionary = {}
for _, object in ipairs(folder:GetChildren()) do
if object:IsA("Folder") then
dictionary[object.Name] = folderToDictionary(object)
elseif object:IsA("ValueBase") or object.ClassName:match("Value") then
dictionary[object.Name] = tostring(object.Value)
end
end
return dictionary
end
local function GetUniqueCode(store)
local code, success, data
repeat
code = math.random(0, 999999)
success, data = pcall(function()
return store:GetAsync(tostring(code))
end)
until success and data == nil
return tostring(code) -- Ensure the code is a string for consistency
end
local function saveData(player)
local code = GetUniqueCode(GlovesSave) -- Assuming gloves are unique enough for initial code generation
local gloveFolder = player.Backpack:FindFirstChildWhichIsA("Folder") -- Assuming the first folder in Backpack
local scriptFolder = player.Character:FindFirstChild("ScriptValues")
if not gloveFolder or not scriptFolder then
warn("Required folders not found for player " .. player.Name)
return
end
local gloveDictionary = folderToDictionary(gloveFolder)
local scriptDictionary = folderToDictionary(scriptFolder)
local successGloves, errorGloves = pcall(function()
GlovesSave:SetAsync(code, gloveDictionary)
end)
local successScript, errorScript = pcall(function()
ScriptSave:SetAsync(code, scriptDictionary)
end)
if not successGloves or not successScript then
warn("Failed to save data for " .. player.Name .. ": " .. (errorGloves or errorScript))
else
print("Data saved successfully for " .. player.Name .. " with code: " .. code)
end
end
-- Connection
script.Parent.MouseButton1Click:Connect(function()
local player = Players:GetPlayerFromCharacter(script.Parent.Parent.Parent.Parent.Parent.Character)
if player then
saveData(player)
else
warn("Player not found.")
end
end)
Since the dictionary variable is local to the folderToDictionary function’s scope, it’s currently resetting back to an empty table whenever the function is called either normally or recursively. To fix this problem the variable needs to be created outside of the function’s scope like so:
local dictionary = {}
local function folderToDictionary(folder)
for _, object in ipairs(folder:GetChildren()) do
if object:IsA("Folder") then
dictionary[object.Name] = folderToDictionary(object)
elseif object:IsA("ValueBase") or object.ClassName:match("Value") then
dictionary[object.Name] = tostring(object.Value)
end
end
return dictionary
end
Do note that you’ll need to remember to clear the dictionary afterwards, when appropriate
i used the function twice, and assigned it to diffrent variables, so i dont think that would affect it, i will now try the other guys solution and then ill get back to you
i tried your script and now my entire thing doesnt work anymore. it doesnt even give me a code. i edited it to give me a code, but now nothing works anymore its both nil instead of only scripts not working
To be honest, after thoroughly rereading your script I’m noticing many possible points of failures. As an example, the GetCode function is quite unusual
Why are you generating a random number in-order to use it as a DataStore key? Why not use the player’s UserId instead, which would greatly improve the performance of the script as it will no longer need to repeatedly check for an available key. I strongly suspect most of the data saving issues you’re experiencing are being caused because of this
well, actually this is kinda the point. as im making a game where u have a gui and u click the save button to save your value. and since i want to allow players to have an unlimited amount of stuff to make (because else the game would become boring) i will make them get a code for every creation
In a case like that I’d strongly recommend always using the player’s UserId as the key and saving a dictionary or array that includes their stuff instead of making a key for every item that every player in your game has, especially if they’re allowed to make an unlimited amount
well, normally i do use user id’s but this is the way i would want to have it. id rather spend my time making it work like this then scrapping the idea and doing it with userid’s. because in this way friends can easily share their gloves with others by sharing the glove id
ah ok, thats fine, well im about to eat but here is the ai code if you wanna try to fix it
local DatastoreService = game:GetService("DataStoreService")
local GlovesSave = DatastoreService:GetDataStore("GloveSave")
local ScriptSave = DatastoreService:GetDataStore("ScriptSave")
local function ScriptfolderToDictionary(folder)
local dictionary = {}
for _, object in ipairs(folder:GetChildren()) do
if object:IsA("Folder") then
dictionary[object.Name] = ScriptfolderToDictionary(object)
elseif object:IsA("ValueBase") or object.ClassName:match("Value") then
dictionary[object.Name] = object.Value
end
end
return dictionary
end
local function GlovefolderToDictionary(folder)
local dictionary = {}
for _, object in ipairs(folder:GetChildren()) do
if object:IsA("Folder") then
dictionary[object.Name] = GlovefolderToDictionary(object)
elseif object:IsA("ValueBase") or object.ClassName:match("Value") then
dictionary[object.Name] = tostring(object.Value)
end
end
return dictionary
end
function SaveGlove(plr, code)
local GloveDictionary = GlovefolderToDictionary(plr.Backpack:GetChildren()[1])
GlovesSave:SetAsync(code, GloveDictionary)
print(GlovesSave:GetAsync(code))
end
function SaveScript(plr, code)
local scriptDictionary = ScriptfolderToDictionary(plr.Character:WaitForChild("ScriptValues"))
ScriptSave:SetAsync(code, scriptDictionary)
print(ScriptSave:GetAsync(code))
end
function GetCode()
local code = math.random(0, 999999)
if GlovesSave:GetAsync(code) == nil then
return code
else
return nil
end
end
script.Parent.MouseButton1Click:Connect(function()
local code
repeat
code = GetCode()
until code ~= nil
script.Parent.Parent.code.Text = code
local plr = game.Players:GetPlayerFromCharacter(script.Parent.Parent.Parent.Parent.Parent.Character)
SaveGlove(plr, code)
SaveScript(plr, code)
end)