183 lines
5.4 KiB
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
|