Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
184 changes: 87 additions & 97 deletions Client/src/init.lua
Original file line number Diff line number Diff line change
@@ -1,137 +1,127 @@
--[[
Data controller
Handles the fetching of the player's data
--]]

local DataController = {}

---------------------
-- Roblox Services --
---------------------
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")
local RunService = game:GetService("RunService")

------------------
-- Dependencies --
------------------
local RobloxLibModules = require(script.Parent["roblox-libmodules"])
local Table = require(RobloxLibModules.Utils.Table)
local DataService;
local DataService
local DataHandlers
local Table = require(script.Parent.Table)

-------------
-- Defines --
-------------
local DataCache;
local PlayerData;
local IsDataLoaded = false

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- @Name : IsDataLoaded
-- @Description : Returns a bool describing whether or not the player's data has been fully replicated in
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function DataController:IsDataLoaded()
return IsDataLoaded
end

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- @Name : GetData
-- @Description : Gets the player's data
-- @Params : OPTIONAL bool "YieldForLoad" - A bool describing whether or not the API will yield for the data to exist
-- OPTIONAL string "Format" - The format to return the data in. Acceptable formats are "Table" and "Folder".
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function DataController:GetData(YieldForLoad,Format)

if YieldForLoad ~= nil then
assert(
typeof(YieldForLoad) == "boolean",
("[Data Service](GetData) Bad argument #2 to 'GetData', bool expected, got %s instead.")
:format(typeof(YieldForLoad))
)
end
if Format ~= nil then
assert(
typeof(Format) == "string",
("[Data Service](GetData) Bad argument #3 to 'GetData', string expected, got %s instead.")
:format(typeof(Format))
)
assert(
string.upper(Format) == "FOLDER" or string.upper(Format) == "TABLE",
("[Data Service](GetData) Bad argument #3 to 'GetData', invalid format. Valid formats are 'Table' or 'Folder', got '%s' instead.")
:format(Format)
)
local DATA_READERS = {}
local DATA_WRITERS = {}
local DataCache
local ChangedCallbacks = {}
local CurrentDataSessionID = ""
local LocalPlayer = Players.LocalPlayer

----------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Helper functions
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
local function WriteData(Writer, ...)
local DataChanges = table.pack(DATA_WRITERS[Writer](DataCache, ...))
local DataName = DataChanges[1]
DataChanges[1] = LocalPlayer

if ChangedCallbacks[DataName] ~= nil then
for _, Callback in pairs(ChangedCallbacks[DataName]) do
Callback(table.unpack(DataChanges))
end
end
end

if YieldForLoad then
while true do
if self:IsDataLoaded() then
break
else
RunService.Stepped:wait()
end
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- API Methods
----------------------------------------------------------------------------------------------------------------------------------------------------------------------

----------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- @Name : ReadData
-- @Description : Calls the specified reader function which reads the given player's savedata
-- @Params : string "Reader" - The name of the reader function to call
-- Tuple "Args" - The arguments to pass to the specified reader function
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
function DataController:ReadData(Reader, ...)
while true do
if not LocalPlayer:IsDescendantOf(game) then
return nil
elseif DataCache ~= nil then
break
end

task.wait()
end

if Format == nil then
return PlayerData,PlayerData:GetAttributes()
elseif string.upper(Format) == "TABLE" then
return Table.ConvertFolderToTable(PlayerData),PlayerData:GetAttributes()
elseif string.upper(Format) == "FOLDER" then
return PlayerData,PlayerData:GetAttributes()
return DATA_READERS[Reader](Table.Copy(DataCache, true), ...)
end

----------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- @Name : OnDataChanged
-- @Description : Invokes the given callback when the specified data is changed
-- @Params : string "DataName" - The name of the data that should be listened to for changes
-- function "ChangedCallback" - The function to invoke when the specified data is changed
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
function DataController:OnDataChanged(DataName, ChangedCallback)
if ChangedCallbacks[DataName] ~= nil then
table.insert(ChangedCallbacks[DataName], ChangedCallback)
else
ChangedCallbacks[DataName] = { ChangedCallback }
end
end

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- @Name : Init
-- @Description : Used to initialize controller state
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- @Description : Called when the service module is first loaded.
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
function DataController:Init()
self:DebugLog("[Data Controller] Initializing...")

DataService = self:GetService("DataService")
DataHandlers = require(DataService:GetDataHandlerModule())
DATA_WRITERS = DataHandlers.Writers
DATA_READERS = DataHandlers.Readers

-----------------------------------
-- Waiting for data to be loaded --
-----------------------------------
local Loaded = false
local LoadedID = DataService:GetDataLoadedQueueID()
self:DebugLog("[Data Controller] Initialized!")
end

DataService.DataLoaded:connect(function(QueueID)
if QueueID == LoadedID then
Loaded = true
end
end)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- @Name : Start
-- @Description : Called after all services are loaded.
----------------------------------------------------------------------------------------------------------------------------------------------------------------------
function DataController:Start()
self:DebugLog("[Data Controller] Running!")

--------------------------------
-- Getting current session ID --
--------------------------------
while true do
if Loaded then
break
else
RunService.Stepped:wait()
end
end
local DataSessionID = LocalPlayer:GetAttribute("SaveSessionID")

local DescendantCount = DataService:GetDataFolderDescendantCount()
DataCache = ReplicatedStorage:WaitForChild("_DataCache")
PlayerData = DataCache:WaitForChild(tostring(Players.LocalPlayer.UserId))
if DataSessionID ~= nil then
CurrentDataSessionID = DataSessionID

while true do
if #self:GetData():GetDescendants() >= DescendantCount then
break
end
RunService.Stepped:wait()
task.wait(0.5)
end
IsDataLoaded = true

self:DebugLog("[Data Controller] Initialized!")
end
DataService.DataLoaded:connect(function(SessionID)
if SessionID == CurrentDataSessionID then
DataCache = DataService:RequestRawData()
end
end)

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- @Name : Start
-- @Description : Used to run the controller
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function DataController:Start()
self:DebugLog("[Data Controller] Running!")

DataService.DataWritten:connect(function(Writer, ...)
if DataCache ~= nil then
WriteData(Writer, ...)
end
end)
end

return DataController
return DataController
Loading
Loading