local DSService = game:GetService('DataStoreService'):GetDataStore('WOOPPOLICE1') local HttpService = game:GetService('HttpService') local defaultData = { PlayerStats = { Name = "None", Title = "None", Rank = "None", Race = "None", Birth = "None", Shirt = "None", Pants = "None", Class = "None", Lives = 5, Days = 0, Money = 0, Karma = 0, Gender = "None", LastRewardTick = "", }, Skills = { Skill1 = { SkillEXP = 0, SkillLevel = 1, SkillRank = "Novice", }, }, Equipment = { Armor = "None", MainHand = "None", OffHand = "None", Epautlet = "None", }, Inventory = { Tools = {}, Materials = {}, } } local function buildDataEntryFromFolder(folder) local dataEntry = {} for _, valueObject in next, folder:GetChildren() do if valueObject:IsA("ValueBase") then dataEntry[valueObject.Name] = {valueType = valueObject.ClassName, value = valueObject.Value} end end return dataEntry end function unloadData(player, data) local newDataFolder = Instance.new("Folder", player) newDataFolder.Name = "PlayerData" local function recursive(folder, children) for x, y in pairs (children) do if typeof(y) == 'table' then local newFolder = Instance.new("Folder", folder) newFolder.Name = x recursive(newFolder, y) elseif typeof(y) == 'number' then local value = Instance.new("NumberValue", folder) value.Name = x value.Value = y elseif typeof(y) == 'string' then local value = Instance.new("StringValue", folder) value.Name = x value.Value = y elseif typeof(y) == 'boolean' then local value = Instance.new("BoolValue", folder) value.Name = x value.Value = y else local value = Instance.new("StringValue", folder) value.Name = x value.Value = y end end end recursive(newDataFolder, data) end local function savePlayerData(player) local dataEntry = buildDataEntryFromFolder(player.PlayerData) DSService:SetAsync(player.UserId, dataEntry) end local function loadPlayerData(player) local dataEntry = DSService:GetAsync(player.UserId) -- In case there's no data found for the player, construct the data folder from a blank template if not dataEntry then dataEntry = defaultData end unloadData(player, dataEntry) end game.Players.PlayerAdded:Connect(function(player) loadPlayerData(player) end) game.Players.PlayerRemoving:Connect(function(player) savePlayerData(player) end)
Fresh data reset, it makes my folder. I change a value to see if it saves or not, I rejoin, and it makes the PlayerData folder, but nothing in it. Been working with this for 6'ish hours with so many different variations and at this point i'm just lost. Any help is VERY much appreciated.
Ok, so the function for turning the data into a folder and value based hierarchy works perfectly. However the problem is that when you go to parse that back into a dictionary you are making an error. The problem is you are looping through the top folder and only inserting data if the children are values. That's why see nothing in the folder because it excludes other folders and there are only folders in the top level. To solve this you should apply what you did in the unload function. Just use recursion and treat the folders as the tables and convert them. Heres my solution:
local DSService = game:GetService('DataStoreService'):GetDataStore('WOOPPOLICE1') local HttpService = game:GetService('HttpService') local defaultData = { PlayerStats = { Name = "None", Title = "None", Rank = "None", Race = "None", Birth = "None", Shirt = "None", Pants = "None", Class = "None", Lives = 5, Days = 0, Money = 0, Karma = 0, Gender = "None", LastRewardTick = "", }, Skills = { Skill1 = { SkillEXP = 0, SkillLevel = 1, SkillRank = "Novice", }, }, Equipment = { Armor = "None", MainHand = "None", OffHand = "None", Epautlet = "None", }, Inventory = { Tools = {}, Materials = {}, } } local function buildDataEntryFromFolder(folder) local function recursive(folder) local parentTable = {} for key,value in pairs(folder:GetChildren()) do -- go through all the primary children of the folder first if value:IsA("ValueBase") then parentTable[key] = value.Value -- if is a normal value put it in its assigned data table elseif value:IsA("Folder") then local t = recursive(value) parentTable[key] = t -- treat folder like a new table end end return parentTable end local dataEntry = recursive(folder) -- i hope this makes sense how i kind of reversed the recursion process in the unloadData function return dataEntry end function unloadData(player, data) local newDataFolder = Instance.new("Folder", player) newDataFolder.Name = "PlayerData" local function recursive(folder, children) for x, y in pairs (children) do if typeof(y) == 'table' then local newFolder = Instance.new("Folder", folder) newFolder.Name = x recursive(newFolder, y) elseif typeof(y) == 'number' then local value = Instance.new("NumberValue", folder) value.Name = x value.Value = y elseif typeof(y) == 'string' then local value = Instance.new("StringValue", folder) value.Name = x value.Value = y elseif typeof(y) == 'boolean' then local value = Instance.new("BoolValue", folder) value.Name = x value.Value = y else local value = Instance.new("StringValue", folder) value.Name = x value.Value = y end end end recursive(newDataFolder, data) end local function savePlayerData(player) local dataEntry = buildDataEntryFromFolder(player.PlayerData) DSService:SetAsync(player.UserId, dataEntry) end local function loadPlayerData(player) local dataEntry = DSService:GetAsync(player.UserId) -- In case there's no data found for the player, construct the data folder from a blank template if not dataEntry then dataEntry = defaultData end unloadData(player, dataEntry) end game.Players.PlayerAdded:Connect(function(player) loadPlayerData(player) end) game.Players.PlayerRemoving:Connect(function(player) savePlayerData(player) end)
Your save data was messed up, heres your fix (look into buildDataEntryFromFolder
)
local DSService = game:GetService('DataStoreService'):GetDataStore('WOOPPOLICE1') local defaultData = { PlayerStats = { Name = "None", Title = "None", Rank = "None", Race = "None", Birth = "None", Shirt = "None", Pants = "None", Class = "None", Lives = 5, Days = 0, Money = 0, Karma = 0, Gender = "None", LastRewardTick = "", }, Skills = { Skill1 = { SkillEXP = 0, SkillLevel = 1, SkillRank = "Novice", }, }, Equipment = { Armor = "None", MainHand = "None", OffHand = "None", Epautlet = "None", }, Inventory = { Tools = {}, Materials = {}, } } local function buildDataEntryFromFolder(folder) local dataEntry = {} local total = 0 recursive = function(tFolder, pFolder) --tableFolder, parentFolder for _, data in pairs(pFolder:GetChildren()) do print(data, data:IsA("ValueBase"), data:IsA("ValueBase") and data.Value or false) tFolder[data.Name] = data:IsA("ValueBase") and data.Value or {} if #data:GetChildren() > 0 then recursive(tFolder[data.Name], data) end end end recursive(dataEntry, folder) return dataEntry end function unloadData(Player, tFolder) Instance.new("Folder", Player).Name = "PlayerData" function recursive(folder, children) for k, v in pairs(children) do local child = Instance.new(typeof(v), folder) child.Name = k if type(v) ~= "table" then child.Value = v else recursive(child, v) end end end recursive(Player.PlayerData, tFolder) end local function savePlayerData(player) local dataEntry = buildDataEntryFromFolder(player.PlayerData) local success, err = pcall(function() DSService:SetAsync(player.UserId, dataEntry) end) if success then print("Saved Successfully") else print("Error: " .. err) end end local function loadPlayerData(player) local dataEntry = DSService:GetAsync(player.UserId) -- In case there's no data found for the player, construct the data folder from a blank template if not dataEntry then dataEntry = defaultData end unloadData(player, dataEntry) end game.Players.PlayerAdded:Connect(loadPlayerData) game.Players.PlayerRemoving:Connect(savePlayerData)