I’ve just come back to a game from about 2-3 months ago, and it was working perfectly fine when I left it, just joined now with a friend and the data system is completely broken.
-- Data module
local data = {
Level = 1
}
return data
-- Main script
local dataStoreService = game:GetService('DataStoreService')
local playerDataStore = dataStoreService:GetDataStore('PlayerDataStore')
local playersData = {}
function updateData(backbone, update)
local new = update
if update == nil then return backbone end
function recurse(tab, ...)
local args = {...}
local target = new
for i = select('#', ...), 1, -1 do
target = target[args[i]]
end
for i, v in next, tab do
if type(v) ~= 'table' or (type(v) == 'table' and target[i] == nil) then
target[i] = v
else
recurse(tab[i], i, ...)
end
end
end
recurse(backbone)
return new
end
function dataManager:GetData(player) -- Fired when player joins
local loadData = playerDataStore:GetAsync(player.UserId) or data
playersData[player.UserId] = updateData(loadData, data)
end
Now I have this updateData table. What this table did was check the ‘new’ data module (located at the top of the script) for any changes to the players saved data. If the player had a new data model missing, it would be added to their data without affecting any of their previous data. Not sure if now something has changed within roblox that screws up this function? But this function has to stay put.
And when I do
print(player, playersData[player.UserId])
after the data is ready, it returns the same table. Well, table, followed by a bunch of numbers and letters, but it’s the same for both players
[Player1 table: 00000255CE9DB340]
[Player2 table: 00000255CE9DB340]
You’re returning the same table as you pass in. When you pass in a table to a function, it passes a reference to the table, so it will be the same table.
1 Like
You pass in two parameters to your function, update and backbone.
You should be modifying backbone, and returning that, however you are modifying the update variable which holds a reference to the data table so it will be the same table anywhere it is used.
You should be doing recurse(new) and settings the target variable to backbone, if I am not mistaken.
2 Likes
When I did this tho
local dataStoreService = game:GetService('DataStoreService')
local playerDataStore = dataStoreService:GetDataStore('PlayerDataStore')
local playersData = {}
function dataManager:GetData(player) -- Fired when player joins
local loadData = playerDataStore:GetAsync(player.UserId) or data
playersData[player.UserId] = loadData
print(player, playersData[player.UserId])
end
And completely got rid of the updateData function, it still occured. So it can’t be anything to do with that function.
It is because of or data
Try using or updateData({}, data)
Could it be because PlayerData is outside PlayerAdded? Since it’s outside wouldnt that mean it gets overidden with the newest players data? But at the same time it makes no sense cause I’ve had it like that forever
No. It’s because you return the data table if no data exists for the user and if several people have no data, they will all use the same data table.
1 Like
If no data exists then they are given the default data. This can’t be the problem
You’re saving a reference to the table. Tables don’t get copied whenever you put them in other variables.
2 Likes
If I did or updateData({}, data) then that means only new players will get the updateData. The point of UpdateData is for players who have a data store already
Then you’ll have to transfer the contents of data into a new table, then assign that.
1 Like
[Player1 table: 00000204E282B3C0]
[Player2 table: 00000204E282B3C0]
local loadData = PlayerDataStore:GetAsync(Player.UserId) or updateData({}, Data)
PlayersData[Player.UserId] = loadData
print(Player, PlayersData[Player.UserId])
Still got the same result
local newData = {};
for i,v in pairs(Data) do
newData[i] = v;
end
Use this code, then assign newData if they do not have any data saved.
This will transfer everything from the default data into a new table.
1 Like
local loadData = playerDataStore:GetAsync(player.UserId) or {ActualDataTableHere}
What do you mean ActualDataTableHere?? the or data is
{
Level = 1
}
I literally mean move that piece of code onto the place of “or data”
But the piece of code is
return {
CurrentBackpack = 'Starter',
CurrentBread = 'Brown',
CurrentDucks = {
{Tier = 1, Rarity = 'Common'},
},
Cash = 0,
Gems = 0,
Happiness = 0,
MaxHappiness = 25,
Rebirths = 0,
Inventory = {
Backpacks = {
'Starter'
},
Breads = {
'Brown'
},
Ducks = {
{Tier = 1, Rarity = 'Common'},
},
},
Codes = {
},
Levels = {
['Frantic Farm'] = false,
['Walters Waterpark'] = false
},
}
Would take up too much space in one line
local loadData = playerDataStore:GetAsync(player.UserId) or {
CurrentBackpack = 'Starter',
CurrentBread = 'Brown',
CurrentDucks = {
{Tier = 1, Rarity = 'Common'},
},
Cash = 0,
Gems = 0,
Happiness = 0,
MaxHappiness = 25,
Rebirths = 0,
Inventory = {
Backpacks = {
'Starter'
},
Breads = {
'Brown'
},
Ducks = {
{Tier = 1, Rarity = 'Common'},
},
},
Codes = {
},
Levels = {
['Frantic Farm'] = false,
['Walters Waterpark'] = false
},
}
1 Like
Wow
That actually worked! Can you explain why using a variable name does not work?? Cause I’ve had it that way for several months and never ran into this problem ever before