Hello everyone! I am making a level based game that stores level data into the player instance when they join. It’s a table with other tables nested, and it works like this: There are two values, TableVersion and HasMap, which are used to determine wether the player can access the map gui (TableVersion is only used if i have to update the table) and then nested tables for each level. Normal levels contain 4 values, “Seen”, “Completed1”, “Completed2”, “Completed3” (they are used for extra challenges). This script that i made also takes account for three boss levels, whose corresponding tables only include “Seen” and “Completed”.
As i was testing the script, I found out that what i was doing didn’t work. The script didn’t return an error, and yet, even though on leave it said it saved the data, on join the saved data was back to the original!
I’ve tried implementing a function to make sure the game has enough time to complete the save pcall before it closes, but still, no luck.
The weird thing is that, as i said before, the script never errors. I’ve implemented some checks to see if everything was working as intended, and it looks like it does. I’ve also implemented a function that prints all nested values inside the table after it has saved them, and it still looks like everything works fine. But it doesn’t! I’m really going crazy over this, if anyone could help I’d appreciate greatly!
This is the script (if it can help, feel free to copy it and try it yourself in studio)
Also, there is another folder which contains data. The table i was talking about before gets converted into a folder whose parent is this second folder, which contains general data that is not bound to the world of the game). It is referred to as MAIN DATA, while the one I’m struggling with is referred to as WORLD SPECIFIC DATA
Nevermind, i figured the error, i was saving it in another part of the datastore
local RepStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local GameDataStore = DataStoreService:GetDataStore("WarpBookStore")
local PlayerDataDestination = "-PlayerData"
local WorldDataDestination = "World0Data"
local function newInstance(name, classId, parent, value)
local i = Instance.new(classId)
i.Name = name
if value then
i.Value = value
end
i.Parent = parent
return i
end
local function printData(myTable)
for k,v in pairs(myTable) do
if typeof(v) == "table" then
for K, V in pairs(v) do
print(tostring(k)..": "..tostring(K)..": "..tostring(V))
end
else
print(tostring(k)..": "..tostring(v))
end
end
end
local function loadData(newPlayer)
local playerDataTable = nil --starts up the variables
local wTable = nil
local didBreak = false
--MAIN DATA RECOVERY
local count = 1
local message
repeat
local success, errorMessage = pcall(function() --fetches main playerdata
playerDataTable = GameDataStore:GetAsync(tostring(newPlayer.UserId)..PlayerDataDestination)
end)
message = errorMessage
until success or count > 3 --repeats the cycle a couple times if it fails
if count > 3 then --if it definitely fails then
warn("[SaveDataScript]: "..message)
didBreak = true
end
----------------------------------
--WORLD SPECIFIC DATA RECOVERY
local count = 1
local message
repeat
local success, errorMessage = pcall(function() --fetches progress data
wTable = GameDataStore:GetAsync(tostring(newPlayer.UserId).."-"..WorldDataDestination)
end)
message = errorMessage
until success or count > 3
if count > 3 then
warn("[SaveDataScript]: "..message)
didBreak = true
end
---------------------------------
--PROCESSING RECOVERY DATA
if not didBreak then
--PROCESSING GENERAL PLAYERDATA
if playerDataTable == nil or playerDataTable["TableVersion"] == 1 then --transforms the data into instances
playerDataTable = {
TableVersion = 2,
Currency = 0
}
end
local PDFolder = newInstance("PlayerData", "Folder", newPlayer)
local TableVersion = newInstance("TableVersion", "IntValue", PDFolder, playerDataTable["TableVersion"])
local Currency = newInstance("Currency", "IntValue", PDFolder, playerDataTable["Currency"])
-----------------------------
printData(wTable)
--PROCESSING WORLD SPECIFIC DATA
if wTable == nil then
warn("Case1")
wTable = {
TableVersion = 5,
HasMap = false,
Level1 = {Seen = false, Completed1 = false, Completed2 = false, Completed3 = false},
Level2 = {Seen = false, Completed1 = false, Completed2 = false, Completed3 = false},
Level3 = {Seen = false, Completed1 = false, Completed2 = false, Completed3 = false},
Level4 = {Seen = false, Completed1 = false, Completed2 = false, Completed3 = false},
Level5 = {Seen = false, Completed1 = false, Completed2 = false, Completed3 = false},
Level6 = {Seen = false, Completed1 = false, Completed2 = false, Completed3 = false},
Level7 = {Seen = false, Completed1 = false, Completed2 = false, Completed3 = false},
Level8 = {Seen = false, Completed1 = false, Completed2 = false, Completed3 = false},
Level9 = {Seen = false, Completed1 = false, Completed2 = false, Completed3 = false},
Level10 = {Seen = false, Completed1 = false, Completed2 = false, Completed3 = false},
Boss1 = {Seen = false, Completed = false},
Boss2 = {Seen = false, Completed = false},
Boss3 = {Seen = false, Completed = false},
}
end
if wTable["TableVersion"] < 5 then --updates the table
warn("Case2")
local newWorldTable = {
TableVersion = 5,
HasMap = wTable["HasMap"],
Level1 = {Seen = wTable["Level1"]["Seen"], Completed1 = wTable["Level1"]["Completed1"], Completed2 = wTable["Level1"]["Completed2"], Completed3 = wTable["Level1"]["Completed3"]},
Level2 = {Seen = wTable["Level2"]["Seen"], Completed1 = wTable["Level2"]["Completed1"], Completed2 = wTable["Level2"]["Completed2"], Completed3 = wTable["Level2"]["Completed3"]},
Level3 = {Seen = wTable["Level3"]["Seen"], Completed1 = wTable["Level3"]["Completed1"], Completed2 = wTable["Level3"]["Completed2"], Completed3 = wTable["Level3"]["Completed3"]},
Level4 = {Seen = wTable["Level4"]["Seen"], Completed1 = wTable["Level4"]["Completed1"], Completed2 = wTable["Level4"]["Completed2"], Completed3 = wTable["Level4"]["Completed3"]},
Level5 = {Seen = wTable["Level5"]["Seen"], Completed1 = wTable["Level5"]["Completed1"], Completed2 = wTable["Level5"]["Completed2"], Completed3 = wTable["Level5"]["Completed3"]},
Level6 = {Seen = wTable["Level6"]["Seen"], Completed1 = wTable["Level6"]["Completed1"], Completed2 = wTable["Level6"]["Completed2"], Completed3 = wTable["Level6"]["Completed3"]},
Level7 = {Seen = wTable["Level7"]["Seen"], Completed1 = wTable["Level7"]["Completed1"], Completed2 = wTable["Level7"]["Completed7"], Completed3 = wTable["Level7"]["Completed3"]},
Level8 = {Seen = wTable["Level8"]["Seen"], Completed1 = wTable["Level8"]["Completed1"], Completed2 = wTable["Level8"]["Completed2"], Completed3 = wTable["Level8"]["Completed3"]},
Level9 = {Seen = wTable["Level9"]["Seen"], Completed1 = wTable["Level9"]["Completed1"], Completed2 = wTable["Level9"]["Completed2"], Completed3 = wTable["Level9"]["Completed3"]},
Level10 = {Seen = wTable["Level10"]["Seen"], Completed1 = wTable["Level10"]["Completed1"], Completed2 = wTable["Level10"]["Completed2"], Completed3 = wTable["Level10"]["Completed3"]},
Boss1 = {Seen = wTable["Boss1"]["Seen"], Completed = wTable["Boss1"]["Completed"]},
Boss2 = {Seen = wTable["Boss2"]["Seen"], Completed = wTable["Boss2"]["Completed"]},
Boss3 = {Seen = wTable["Boss3"]["Seen"], Completed = wTable["Boss3"]["Completed"]},
}
wTable = newWorldTable
warn("Case2 done")
end
local wFolder = newInstance(WorldDataDestination, "Folder", PDFolder)
local TableVersion = newInstance("TableVersion", "IntValue", wFolder, wTable["TableVersion"])
local hasMap = newInstance("HasMap", "BoolValue", wFolder, wTable["HasMap"])
for i = 1, 10 do
local Lv = newInstance("Level"..tostring(i), "Folder", wFolder)
local seen = newInstance("Seen", "BoolValue", Lv, wTable["Level"..tostring(i)]["Seen"])
local comp1 = newInstance("Completed1", "BoolValue", Lv, wTable["Level"..tostring(i)]["Completed1"])
local comp2 = newInstance("Completed2", "BoolValue", Lv, wTable["Level"..tostring(i)]["Completed2"])
local comp3 = newInstance("Completed3", "BoolValue", Lv, wTable["Level"..tostring(i)]["Completed3"])
end
for i = 1, 3 do
local boss = newInstance("Boss"..tostring(i), "Folder", wFolder)
local seen = newInstance("Seen", "BoolValue", boss, wTable["Boss"..tostring(i)]["Seen"])
local comp = newInstance("Completed", "BoolValue", boss, wTable["Boss"..tostring(i)]["Completed"])
end
print("Loaded data for "..newPlayer.Name)
RepStorage.RemoteEvents.MapEvent:FireClient(newPlayer, "RedrawGui", wTable)
else
newPlayer:Kick("Sorry! There was a problem while loading your save data! Please rejoin in a bit")
warn("Could not fetch save data for "..newPlayer.Name.." so they were kicked")
end
end
local function saveData(remPlayer)
local PDFolder = remPlayer.PlayerData
local wFolder = PDFolder:FindFirstChild(WorldDataDestination) --CHANGE THIS TO THE FOLDER THE WORLD IS USING
local didBreak = false
--FETCHING PLAYER DATA
local PlayerDataTable = { --creates the general table to save
TableVersion = PDFolder.TableVersion.Value,
Currency = PDFolder.Currency.Value,
}
----------------------
--FETCHING WORLD SPECIFIC DATA
local WorldTable = {
TableVersion = wFolder.TableVersion.Value,
HasMap = wFolder.HasMap.Value,
Level1 = {Seen = wFolder.Level1.Seen.Value, Completed1 = wFolder.Level1.Completed1.Value, Completed2 = wFolder.Level1.Completed2.Value, wFolder.Level1.Completed2.Value},
Level2 = {Seen = wFolder.Level2.Seen.Value, Completed1 = wFolder.Level2.Completed1.Value, Completed2 = wFolder.Level2.Completed2.Value, wFolder.Level2.Completed2.Value},
Level3 = {Seen = wFolder.Level3.Seen.Value, Completed1 = wFolder.Level3.Completed1.Value, Completed2 = wFolder.Level3.Completed2.Value, wFolder.Level3.Completed2.Value},
Level4 = {Seen = wFolder.Level4.Seen.Value, Completed1 = wFolder.Level4.Completed1.Value, Completed2 = wFolder.Level4.Completed2.Value, wFolder.Level4.Completed2.Value},
Level5 = {Seen = wFolder.Level5.Seen.Value, Completed1 = wFolder.Level5.Completed1.Value, Completed2 = wFolder.Level5.Completed2.Value, wFolder.Level5.Completed2.Value},
Level6 = {Seen = wFolder.Level6.Seen.Value, Completed1 = wFolder.Level6.Completed1.Value, Completed2 = wFolder.Level6.Completed2.Value, wFolder.Level6.Completed2.Value},
Level7 = {Seen = wFolder.Level7.Seen.Value, Completed1 = wFolder.Level7.Completed1.Value, Completed2 = wFolder.Level7.Completed2.Value, wFolder.Level7.Completed2.Value},
Level8 = {Seen = wFolder.Level8.Seen.Value, Completed1 = wFolder.Level8.Completed1.Value, Completed2 = wFolder.Level8.Completed2.Value, wFolder.Level8.Completed2.Value},
Level9 = {Seen = wFolder.Level9.Seen.Value, Completed1 = wFolder.Level9.Completed1.Value, Completed2 = wFolder.Level9.Completed2.Value, wFolder.Level9.Completed2.Value},
Level10 = {Seen = wFolder.Level10.Seen.Value, Completed1 = wFolder.Level10.Completed1.Value, Completed2 = wFolder.Level10.Completed2.Value, wFolder.Level10.Completed2.Value},
Boss1 = {Seen = wFolder.Boss1.Seen.Value, Completed = wFolder.Boss1.Seen.Value},
Boss2 = {Seen = wFolder.Boss2.Seen.Value, Completed = wFolder.Boss2.Seen.Value},
Boss3 = {Seen = wFolder.Boss3.Seen.Value, Completed = wFolder.Boss3.Seen.Value},
}
--------------------
--SAVING PLAYER DATA
local count = 1
local msg = ""
repeat
local success, eMessage = pcall(function()
GameDataStore:SetAsync(tostring(remPlayer.UserId)..PlayerDataDestination, PlayerDataTable)
end)
msg = eMessage
until success or count > 3
if count > 3 then
print("[SaveDataScript]: "..msg)
didBreak = true
end
--------------------
--SAVING WORLD SPECIFIC DATA
local count = 1
local msg = ""
repeat
local success, eMessage = pcall(function()
GameDataStore:SetAsync(tostring(remPlayer.UserId)..WorldDataDestination, WorldTable)
end)
until success or count > 3
if count > 3 then
print("[SaveDataScript]: "..msg)
didBreak = true
end
-------------------
printData(WorldTable)
if didBreak == true then
warn("Could not save "..remPlayer.Name.."'s data")
else
print("Saved data for "..remPlayer.Name)
end
end
Players.PlayerAdded:Connect(function(newPlayer)
loadData(newPlayer)
end)
Players.PlayerRemoving:Connect(function(remPlayer)
saveData(remPlayer)
end)
game:BindToClose(function()
if game:GetService("RunService"):IsStudio() then
wait(3)
end
end)