I just created this data store and I’ve done some testing, it works well, but are there any flaws?
local dataStore = {}
local DSS = game:GetService("DataStoreService")
local AutoSaveInterval = 30
function dataStore.wrap(self)
local PlayerId = string.format("Player_%d", self.player.UserId)
local function save()
if #self.__queue == 0 then
-- There are no entries, nothing needs to happen
return
end
-- Update the data store to be the last entry
self.__store:SetAsync(PlayerId, self.__queue[#self.__queue])
end
game:BindToClose(function()
-- The game has been shutdown, wait until the player's next save and call save()
delay(tick()-self.__lastEntry, save)
end)
-- Wait every 30 seconds to save data
while wait(AutoSaveInterval) do
-- Change the last entry
self.__lastEntry = tick()
-- Call save()
save()
for entry, _ in pairs(self.__queue) do
-- Remove all entries from the queue
table.remove(self.__queue, entry)
end
end
end
function dataStore.new(player, name, defaultValue)
if dataStore[player] then
-- Return the data store if it already exists
return dataStore[player]
end
-- Create data store object
dataStore[player] = setmetatable({
name = name,
player = player,
defaultValue = defaultValue,
__lastEntry = math.huge,
__queue = {},
__store = DSS:GetDataStore(name),
__updateCallbacks = {},
}, {__index = dataStore})
-- Start auto saving
coroutine.wrap(dataStore.wrap)(dataStore[player])
-- Return data store
return dataStore[player]
end
function dataStore:GetAsync(default)
local default = default or self.defaultValue or 0
local PlayerId = string.format("Player_%d", self.player.UserId)
if #self.__queue > 0 then
-- Not all requests are saved right away, so we get the last entry
return self.__queue[#self.__queue]
else
local found, result = pcall(function()
return self.__store:GetAsync(PlayerId)
end)
if found then
-- Data was found, if there is no saved data then return the default value
return result or default
else
local err = string.format("Data store experienced an error: %q", result)
warn(err)
end
end
end
function dataStore:SetAsync(value)
-- Add value to queue so it can be saved
table.insert(self.__queue, value)
-- Call all update callbacks
for _, callback in pairs(self.__updateCallbacks) do
callback(value)
end
end
function dataStore:OnUpdate(callback)
table.insert(self.__updateCallbacks, callback)
end
return dataStore