Clients/Client2018/content/internal/AppShell/Modules/Shell/ReloaderManager.lua

183 lines
5.4 KiB
Lua

local HttpService = game:GetService('HttpService')
local PlatformService = nil
pcall(function() PlatformService = game:GetService('PlatformService') end)
local ThirdPartyUserService = nil
pcall(
function()
ThirdPartyUserService = game:GetService("ThirdPartyUserService")
end
)
local currentUserState = nil
if ThirdPartyUserService then
ThirdPartyUserService.ActiveUserSignedOut:connect(
function()
currentUserState = {}
end
)
end
local reloaders = {}
local ReloaderManager = {}
do
--[Reloader]--
--Add
function ReloaderManager:addReloader(reloaderName)
if (reloaders[reloaderName] == nil) then
reloaders[reloaderName] = {}
end
end
--Call
function ReloaderManager:callReloader(reloaderName, internal)
if reloaders[reloaderName] == nil then return end
for key, value in pairs(reloaders[reloaderName]) do
ReloaderManager:callReloaderFunc(reloaderName, key, internal)
end
end
--Remove
function ReloaderManager:removeReloader(reloaderName)
if reloaders[reloaderName] == nil then return end
for key, value in pairs(reloaders[reloaderName]) do
reloaders[reloaderName][key] = nil
end
reloaders[reloaderName] = nil
end
--[Reloader Func]--
local function GetReloaderFuncObj(reloaderId, funcId)
if not reloaderId or not funcId then return end
if reloaders[reloaderId] and reloaders[reloaderId][funcId] then
return reloaders[reloaderId][funcId]
end
end
--Add reloaderfunc, will excute the reloaderFunc at intervals
--Each reloader may has several reloaderFuncs since we may want to refresh different element at different intervals
--reloaderName: the name of reloader, usually describle what the reloader works for
--reloaderFunc: function to be called when reloader
--interval: interval to reload(seconds)
function ReloaderManager:addReloaderFunc(reloaderName, reloaderFunc, interval, userRelated)
--Don't make duplicated reloaderfuncs
if reloaders[reloaderName] then
return
end
ReloaderManager:addReloader(reloaderName)
--We use GUID to differentiate reloaderfuncs, avoid to make redundant thread
local funcId = HttpService:GenerateGUID()
reloaders[reloaderName][funcId] =
{
reloaderFunc = reloaderFunc,
interval = interval,
userRelated = userRelated,
lastUpdateTime = nil,
suspend = false,
mutex = false,
lastUserState = userRelated and currentUserState
};
--Reload logic
spawn(function()
while GetReloaderFuncObj(reloaderName, funcId) do
local ReloaderFuncObj = GetReloaderFuncObj(reloaderName, funcId)
local realInterval = ReloaderFuncObj.interval
if ReloaderFuncObj.lastUpdateTime then
--If we made any manually call between intervals, we should use the ReloaderFuncObj.lastUpdateTime as the new
--start time to make sure the data is always not outdated
local timeToLastUpdate = tick() - ReloaderFuncObj.lastUpdateTime
if timeToLastUpdate < realInterval then
realInterval = realInterval - timeToLastUpdate
end
end
wait(realInterval)
local lastUserState = ReloaderFuncObj.lastUserState
local userRelated = ReloaderFuncObj.userRelated
if not userRelated or lastUserState == currentUserState then
ReloaderManager:callReloaderFunc(reloaderName, funcId, true)
else
ReloaderManager:removeReloaderFunc(reloaderName, funcId)
end
end
end)
return funcId
end
--Remove
function ReloaderManager:removeReloaderFunc(reloaderName, funcId)
if reloaders[reloaderName] == nil or reloaders[reloaderName][funcId] == nil then
return
end
reloaders[reloaderName][funcId] = nil
end
--Update(interval, reloaderFunc, suspend)
function ReloaderManager:updateReloaderFunc(reloaderName, funcId, newAttrs)
local Reloader = GetReloaderFuncObj(reloaderName, funcId)
if not Reloader then
return
end
if newAttrs and type(newAttrs) == 'table' then
for k, v in pairs(newAttrs) do
Reloader[k] = v
end
end
end
function ReloaderManager:suspendReloaderFunc(reloaderName, funcId)
ReloaderManager:updateReloaderFunc(reloaderName, funcId, {suspend = true})
end
function ReloaderManager:resumeReloaderFunc(reloaderName, funcId)
ReloaderManager:updateReloaderFunc(reloaderName, funcId, {suspend = false})
end
--Call reloaderFunc, default is a manually call on reloaderFunc
function ReloaderManager:callReloaderFunc(reloaderName, funcId, internal)
local ReloaderFuncObj = GetReloaderFuncObj(reloaderName, funcId)
if ReloaderFuncObj and ReloaderFuncObj.reloaderFunc then
local CallFunc = false
--Call inside Reloader Manager
if internal then
if not ReloaderFuncObj.suspend and not ReloaderFuncObj.mutex then
if not ReloaderFuncObj.lastUpdateTime or tick() - ReloaderFuncObj.lastUpdateTime >= ReloaderFuncObj.interval then
CallFunc = true
end
end
else --Get Called from outside, manually call
if not ReloaderFuncObj.mutex then
CallFunc = true
end
end
if CallFunc then
ReloaderFuncObj.mutex = true
ReloaderFuncObj.lastUpdateTime = tick()
ReloaderFuncObj.reloaderFunc()
ReloaderFuncObj.mutex = false
end
end
end
--Call all reloader funcs on resume
if not UserSettings().GameSettings:InStudioMode() or game:GetService('UserInputService'):GetPlatform() == Enum.Platform.Windows then
pcall(function() PlatformService.Resumed:connect(function()
for _, reloader in pairs(reloaders) do
spawn(function()
ReloaderManager:callReloader(reloader, true)
end)
end
end)
end)
end
end
return ReloaderManager