I am trying to create a function which compares a players data folder with the main data folder which is given to new players. If I add a new number value to the main data folder such as “Gold” I want it to be able to carry over to the player’s data folder next time they join as their saved data folder will not have this new value.
For example:
Say this is the original folder and I wanted to add a new value named “Hunger”
Like so:
How would I make it so the players who have their data saved without the “Hunger” value could have it added to their folder the next time they joined.
I couldn’t really get my head around this and got a bit confused.
From what I recall, you can just add the value to the array/default data and it’ll do the work for you. Just to be sure, would you mind showing the structure of your default data?
I think I understand what you’re going for here. I use table deep merging for this without ValueBase or Folder instances. I store the schema version of the data table as a key, and compare it to the version of the schema template.
If the schema version of loaded data is higher, the merge is an “overwriter” / authoritative, meaning that if a key does not exist in the merge target (the schema template copy), it is added anyway. The same principles apply here. This will protect you from players joining older servers with newer data.
Then, you simply save all data indiscrimantly.
Good that you’re handling this. Many developers don’t, and I suspect it’s a major source of data loss.
I’m not quite sure how to do this, is there any tutorials? I was thinking of comparing the two folders descendants and checking for differences but I could not think of a way to do so.
If you want to tell if two folders are “equal”, it’d be something like this:
local function is_folders_equal(first, second)
local first_children = first:GetChildren()
for index = 1, #first_children do
local child = first_children[index]
local child_in_second = second:FindFirstChild(child.Name)
if child_in_second == nil then
return false
end
if child_in_second.ClassName ~= child.ClassName then
return false
end
if child:IsA("ValueBase") then
if child.Value ~= child_in_second.Value then
return false
end
elseif child:IsA("Folder") then
if is_folders_equal(child, child_in_second) == false then
return false
end
end
end
return true
end
I’ll delete my last reply since it seems irrelevant to what you’re asking.
I tried doing this however both “Current” and “Original” eventually became nil
Current is the Players loaded data folder and original is the folder which is given to new players with no data.
I want it to be able to detect if there is new values and add them to the players fodler if so,
function compare(Original, Current)
for _, Object in pairs(Original:GetChildren()) do
if Current:FindFirstChild(Object.Name) == nil then
Object:Clone().Parent = Current
else
compare(Original[Object.Name], Current[Object.Name])
end
end
end
Not quite sure i understand what your asking, but I use this function to match two tables upon join without erasing any saved data. You can probably modify this to work with your folder structure or use it as is to compare the servers current saved data structure with the players saved data.
--Adds any missing indexes to loaded data.
local function halfMatch(TableToMatch,LoadedData) --Table To Match, Loaded Data
LoadedData=LoadedData or {}
for i,v in pairs (TableToMatch) do
if (type(v)=="table") then
LoadedData[i]=halfMatch(v,LoadedData[i])
elseif (LoadedData[i]==nil) then
LoadedData[i]=v
end
end
return LoadedData
end
Something like this is what you’d want, but this is a very awkward way to implement player data management:
local value_classes = {
bool = "BoolValue",
number = "NumberValue",
string = "StringValue",
}
local function add_data_to_folder(data, folder)
for key, value in pairs(data) do
if type(value) == "table" then
local new_folder = Instance.new("Folder")
new_folder.Name = key
add_data_to_folder(value, new_folder)
else
local new_class = value_classes[type(value)]
local new_value = Instance.new(new_class)
new_value.Name = key
new_value.Parent = folder
end
end
end
It turns out my code was actually fine from the beginning, it was breaking because I had one of the folders named as “Name”. Class members have a higher priority then children.