Skip to content

Instantly share code, notes, and snippets.

@howmanysmall
Created August 6, 2020 17:10
Show Gist options
  • Save howmanysmall/483ce7aec5436058b226077fedf31ee2 to your computer and use it in GitHub Desktop.
Save howmanysmall/483ce7aec5436058b226077fedf31ee2 to your computer and use it in GitHub Desktop.
local RunService = game:GetService("RunService")
local Heartbeat = RunService.Heartbeat
local LinkToInstanceIndex = newproxy(false)
local Janitors = setmetatable({}, {__mode = "k"})
local Janitor = {__index = {CurrentlyCleaning = true}}
local TypeDefaults = {
["function"] = true;
["RBXScriptConnection"] = "Disconnect";
}
local function Wait(Seconds)
Seconds = math.max(Seconds or 0.03, 0)
local TimeRemaining = Seconds
while TimeRemaining > 0 do
TimeRemaining -= Heartbeat:Wait()
end
return Seconds - TimeRemaining
end
local function Finish(Thread, Success, ...)
if not Success then
warn(debug.traceback(Thread, tostring((...))))
end
return Success, ...
end
local function FastSpawn(Function, ...)
local Thread = coroutine.create(Function)
return Finish(Thread, coroutine.resume(Thread, ...))
end
function Janitor.new()
return setmetatable({CurrentlyCleaning = false}, Janitor)
end
function Janitor.__index:Add(Object, MethodName, Index)
if Index then
self:Remove(Index)
local This = Janitors[self]
if not This then
This = {}
Janitors[self] = This
end
This[Index] = Object
end
self[Object] = MethodName or TypeDefaults[typeof(Object)] or "Destroy"
return Object
end
function Janitor.__index:Remove(Index)
local This = Janitors[self]
if This then
local Object = This[Index]
if Object then
local MethodName = self[Object]
if MethodName then
if MethodName == true then
Object()
else
Object[MethodName](Object)
end
self[Object] = nil
end
This[Index] = nil
end
end
end
function Janitor.__index:Get(Index)
local This = Janitors[self]
if This then
return This[Index]
end
end
function Janitor.__index:Cleanup()
if not self.CurrentlyCleaning then
self.CurrentlyCleaning = nil
for Object, MethodName in next, self do
if MethodName == true then
Object()
else
Object[MethodName](Object)
end
self[Object] = nil
end
local This = Janitors[self]
if This then
for Index in next, This do
This[Index] = nil
end
Janitors[self] = nil
end
self.CurrentlyCleaning = false
end
end
local NULL = nil
function Janitor.__index:Destroy()
self:Cleanup()
setmetatable(self, NULL)
end
Janitor.__call = Janitor.__index.Cleanup
--- Makes the Janitor clean up when the instance is destroyed
-- @param Instance Instance The Instance the Janitor will wait for to be Destroyed
-- @returns Disconnectable table to stop Janitor from being cleaned up upon Instance Destroy (automatically cleaned up by Janitor, btw)
-- @author Corecii
local Disconnect = {Connected = true}
Disconnect.__index = Disconnect
function Disconnect:Disconnect()
self.Connected = false
self.Connection:Disconnect()
end
function Janitor.__index:LinkToInstance(Object, AllowMultiple)
local Reference = Instance.new("ObjectValue")
Reference.Value = Object
local ManualDisconnect = setmetatable({}, Disconnect)
local Connection
local function ChangedFunction(Obj, Par)
if not Reference.Value then
ManualDisconnect.Connected = false
return self:Cleanup()
elseif Obj == Reference.Value and not Par then
Obj = nil
Wait(0.03)
if (not Reference.Value or not Reference.Value.Parent) and ManualDisconnect.Connected then
if not Connection.Connected then
ManualDisconnect.Connected = false
return self:Cleanup()
else
while true do
Wait(0.2)
if not ManualDisconnect.Connected then
return
elseif not Connection.Connected then
ManualDisconnect.Connected = false
return self:Cleanup()
elseif Reference.Value.Parent then
return
end
end
end
end
end
end
Connection = Object.AncestryChanged:Connect(ChangedFunction)
ManualDisconnect.Connection = Connection
Object = nil
FastSpawn(ChangedFunction, Reference.Value, Reference.Value.Parent)
if AllowMultiple then
self:Add(ManualDisconnect, "Disconnect")
else
self:Add(ManualDisconnect, "Disconnect", LinkToInstanceIndex)
end
return ManualDisconnect
end
return Janitor
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment