Are you able to provide the whole stack trace in your console? I find it odd that a string was passed to addressTable even though as far as I can see, it only passes values that are tables. Does it specify where else the issue occurs (either by the prefab location or by the review of fetched player data)?
13:31:59.071 - Stack Begin
13:31:59.072 - Script 'ServerScriptService.Core.GameManager.PlayerManager.DataManager', Line 125 - upvalue addressTable
13:31:59.075 - Script 'ServerScriptService.Core.GameManager.PlayerManager.DataManager', Line 126 - upvalue addressTable (x2)
13:31:59.076 - Script 'ServerScriptService.Core.GameManager.PlayerManager.DataManager', Line 126 - local addressTable
13:31:59.077 - Script 'ServerScriptService.Core.GameManager.PlayerManager.DataManager', Line 133 - method GetData
13:31:59.078 - Script 'ServerScriptService.Core.GameManager.PlayerManager', Line 13
13:31:59.080 - Stack End
For reference, Line 125 is the line where I have written --ERROR ON THIS LINE!! in the code
Lines 125 and 126 are what I assume are the table failing to run since non-table values are being passed to addressTable. What is Line 133, the function “GetData” and what do you currently use that for?
for key, value in pairs(receivedValue) do -- LINE 125
tableToReturn[key] = (type(receivedValue) == 'table' and addressTable(value) or value) -- Line 126
end
for k, v in pairs(data) do -- assuming "data" is your prefab, changed that part for you
playersData[player.UserId][k] = (type(v) == "table" and addressTable(v)) or v -- LINE 133
end
I’m under massive confusion. I’ll try and make a repro if the solution doesn’t somehow magically float its way to you, if that doesn’t trouble you too much.
Yea I got no clue what is going
Whatevers easiest
scripting is so weird. i made the wonkiest repro and it worked.
Basically, I’ve given up all hope on trying to be graceful about it and I’m just letting the function handle all the work. It worked, but it may not be to your liking. I don’t even know what I did, it’s like black magic. I can’t fully comprehend what I did, but I know it works.
-- addressTable should now look like this. Replace the entire thing with this. Put it outside PlayerAdded if you can.
local function addressTable(receivedValue)
local function produceTable(fromValue)
local tableToReturn = {}
for key, value in pairs(receivedValue) do -- yes
tableToReturn[key] = addressTable(value)
end
return tableToReturn
end
return type(receivedValue) == "table" and produceTable(receivedValue) or receivedValue
end
-- Change anything that looks like below
(type(receivedValue) == 'table' and addressTable(value) or value)
-- to this:
addressTable(value)
Repro (my whole script except on an empty file):
weird data thing repro.rbxl (12.1 KB)
Trials below (using Crazyman32’s Data Store Editor plugin).
Trial result 1 (using test variable “timeOfUpdateTest”):
Trial result 2 (wiped everything except the array):
Mission success? I HOPE. PLEASE. THERE WERE NO ERRORS AND I USED ACCURATE PLAY SOLO.
Well it’s fixed those problems, and no errors but still doing the same thing as before
If I reset the data store, comment out any mention of the Scout, and run, yada yada works all good. Then leave, Uncomment the scout so it’s now part of the prefab, put a print(user.Classes.Scout) it prints nil.
Printing (user.Classes.Knight) and (user.Classes.Archer) prints a table, but no print for Scout. If I reset data store again, and join WITH scout in the table, then it prints Scout. But yea, not adding it to the player if they already have a data store
This is from your test place as well, just incase I put them in the wrong spot in my scripts
time for emergency sos request.
I’m sure that the strategy I had would’ve worked. The main thing I want to tackle is using your save data as configuration as opposed to using raw data so it’s easier to add things as you need, but apparently this has made the process a whole lot more complicated.
I think a new approach may have to be taken. I have any number of ways to go about it, such as changing class data to be saved as scopes to data stores (thus also decreasing the size of your primary data store).
Rip I got no clue what else to do
Tried messing around with the place more to see if I could magically come up with a fix but yeah nothing
Sorry we couldn’t work out a solution with what I provided. Hope someone comes along with a better fix than mine and good luck with your game.
Thanks for the time and effort though
Just been messing around with it, and ye, it still works with variables being added/removed whatever, but ye, not arrays
I made this little script for you (I didn’t test it).
This should update all the variables on the old object including tables.
function updateObject(old, new)
local update = {}
for name, variable in next, new do
update[name] = (type(variable) == 'table' and old[name] and updateObject(old[name], variable)) or old[name] or variable
end
return update
end
Would I need to delete anything I already have?? And when would I call (updateObject)??
Guessing old would be the players data store, and new would be the preset one?
I’m not sure what you already have. I didn’t read the comment above. But you are correct. old is the old table that could need updating and new is the present one.
So in your case old is the decoded data off the datastore.
Ok, well Ill chuck it in and mess with it
Btw, current code I have is pasted in this thread
I just plonked it in, not really knowing what needs to be changed, removed, but heres what I got
local data = {
Classes = {
['Knight'] = {
['ID'] = 1,
['Owned'] = true,
['Weapons'] = {
'Classic Sword',
},
['Armours'] = {
'Knight Armour'
},
['Trails'] = {
'None'
},
},
['Archer'] = {
['ID'] = 2,
['Owned'] = true,
['Weapons'] = {
'Bow and Arrow'
},
['Armours'] = {
'Archer Armour'
},
['Trails'] = {
'None'
},
},
['Scout'] = {
['ID'] = 3,
['Owned'] = false,
['Weapons'] = {
'Dagger'
},
['Armours'] = {
'Scout Armour'
},
['Trails'] = {
'None'
},
},
},
ClassEquips = {
EquippedKnight = {
Weapon = 'Classic Sword',
Armour = 'Knight Armour',
Trail = 'None'
},
EquippedArcher = {
Weapon = 'Bow and Arrow',
Armour = 'Archer Armour',
Trail = 'None'
},
EquippedScout = {
Weapon = 'Dagger',
Armour = 'Scout Armour',
Trail = 'None'
},
},
EquippedClass = 'Knight',
Level = 1,
Exp = 0,
Gold = 100,
Gems = 0,
}
local httpService = game:GetService("HttpService")
local playerDataStore = game:GetService("DataStoreService"):GetDataStore("test005")
local playersData = {}
function updateObject(old, new)
local update = {}
for name, variable in next, new do
update[name] = (type(variable) == 'table' and old[name] and updateObject(old[name], variable)) or old[name] or variable
end
return update
end
game.Players.PlayerAdded:Connect(function(player)
playersData[player.UserId] = {}
local function addressTable(receivedValue)
local function produceTable(fromValue)
local tableToReturn = {}
for key, value in pairs(receivedValue) do -- yes
tableToReturn[key] = addressTable(value)
end
return tableToReturn
end
return type(receivedValue) == "table" and produceTable(receivedValue) or receivedValue
end
for k, v in pairs(data) do -- assuming "data" is your prefab, changed that part for you
playersData[player.UserId][k] = addressTable(v) -- yes
end
local loadJSON = playerDataStore:GetAsync(player.UserId)
local setData = (loadJSON and httpService:JSONDecode(loadJSON)) or nil
-- Data part
if setData then
for key, value in pairs(setData) do
if playersData[player.UserId][key] then
playersData[player.UserId][key] = addressTable(value)
end
end
end
updateObject(playersData[player.UserId], data)
local user = playersData[player.UserId]
print(user.Classes.Scout)
end)
game.Players.PlayerRemoving:Connect(function (player)
local saveJSON = httpService:JSONEncode(playersData[player.UserId])
playerDataStore:SetAsync(player.UserId, saveJSON)
end)
Didnt actually seem to change anything, probs cause I did it completely wrong
This is how it should work.
game.Players.PlayerAdded:Connect(function(player)
local loadJSON = playerDataStore:GetAsync(player.UserId)
local setData = (loadJSON and httpService:JSONDecode(loadJSON)) or {}}
playersData[player.UserId] = updateObject(setData, data)
local user = playersData[player.UserId]
print(user.Classes.Scout)
end)
Ill also test it in a minute to check that it’s working.
No way…
It seems to be working atm! Just going through and testing to make sure every bit of it is saving, as well as picking up if anything new is added
Yea, I have ran a test and its working fine.
function updateObject(old, new)
local update = {}
for name, variable in next, new do
update[name] = (type(variable) == 'table' and old[name] and updateObject(old[name], variable)) or old[name] or variable
end
return update
end
local old = {test1 = "hello", test2 = {"a", "b", "c"}, test3 = 'test'}
local new = {test0 = "hey", test1 = "hello", test2 = {"a", "b", "c", "d", "e"}}
local updatedTable = updateObject(old, new)
for i,v in next, updatedTable do
print(i,v)
if type(v) == 'table' then
for i,v in next, v do
print('\t', i, v)
end
end
end
--[[
OUTPUT:
test0 hey
test1 hello
test2 table: 000001F7B0EBE900
1 a
2 b
3 c
4 d
5 e
--]]