I’d like to see if anyone has any thoughts on how to improve my datastore module. In particle, with regard to .refreshData()
, is there a better way to implement this.
local DataStoreService = game:GetService("DataStoreService")
local dataStore = DataStoreService:GetDataStore("PlayerData")
local eventsFolder = game:GetService("ReplicatedStorage"):WaitForChild("Events")
local pcallGetAsync = function(userId)
local rawSave
local success, issue = pcall(function()
rawSave = dataStore:GetAsync(tostring(userId))
end)
return success, issue, rawSave
end
local pcallSetAsync = function(userId, data)
local success, issue = pcall(function()
dataStore:SetAsync(tostring(userId), data)
end)
return success, issue
end
local module = {}
module.defaultTable = {
gameInfo = {
jump = 0;
checkpoint = 0;
};
inventory = {
items = {
revives = 0;
};
titles = {
{
name = "Cool";
price = 500;
rarity = 1;
}
};
};
}
module.dataCache = {}
module.refreshData = function(rawSave)
local defaultTable = module.defaultTable
local currentTable = rawSave
if currentTable == nil then
currentTable = {}
end
for key, value in pairs(defaultTable) do
if currentTable[key] == nil then
currentTable[key] = value
elseif type(value) == "table" then
for key2, value2 in pairs(value) do
if currentTable[key][key2] == nil then
currentTable[key][key2] = value2
elseif type(value2) == "table" then
for key3, value3 in pairs(value2) do
if currentTable[key][key2][key3] == nil then
currentTable[key][key2][key3] = value3
elseif type(value3) == "table" then
for key4, value4 in pairs(value3) do
if currentTable[key][key2][key3][key4] == nil then
currentTable[key][key2][key3][key4] = value4
elseif type(value4) == "table" then
for key5, value5 in pairs(value4) do
if currentTable[key][key2][key3][key4][key5] == nil then
currentTable[key][key2][key3][key4][key5] = value5
end
end
end
end
end
end
end
end
end
end
return currentTable
end
module.pullFromCloud = function(player)
local userId = player.UserId
local success, issue, rawSave = pcallGetAsync(userId)
if success == false then
warn("An error occurred while loading data for player "..tostring(player.Name)..": "..issue)
wait(2)
success, issue, rawSave = pcallGetAsync(userId)
if success == false then
warn("Another error occurred while loading data for player "..tostring(player.Name)..": "..issue)
player:Kick("An issue occurred while loading your data. Please rejoin in a few minutes or try again later. Specifically: "..issue)
else
return rawSave
end
else
return rawSave
end
end
module.pushToCloud = function(player)
local userId = player.UserId
local cachedSave = module.dataCache[userId]
module.dataCache[userId] = nil
local success, issue = pcallSetAsync(userId, cachedSave)
if success == false then
warn("An error occurred while saving data for player "..tostring(player.Name)..": "..issue)
wait(2)
success, issue = pcallGetAsync(userId)
if success == false then
warn("Another error occurred while loading data for player "..tostring(player.Name)..": "..issue)
wait(2)
success, issue = pcallGetAsync(userId)
if success == false then
error("A critical error occurred while attempting to save data for player "..tostring(player.Name)..": "..issue)
end
end
end
end
module.getCache = function(player)
local userId = player.UserId
if module.dataCache[userId] == nil then
local rawSave = module.pullFromCloud(player)
local refreshedSave = module.refreshData(rawSave)
module.dataCache[userId] = refreshedSave
end
return module.dataCache[userId]
end
module.updateCache = function(player, transformFunction)
local cachedSave = module.dataCache[player.UserId]
local modifiedSave = transformFunction(cachedSave)
module.dataCache[player.UserId] = modifiedSave
eventsFolder:WaitForChild("UpdateData"):InvokeClient(player, modifiedSave)
end
return module
A few notes:
- I chose to use caching so intensively because my game will be rapidly updating the values, and thus would not be able to easily fit into the traditional datastore limits.
-
defaultTable
will reflect the lastest format of the save data. This makes it easy to add new features.