Skip to content

Instantly share code, notes, and snippets.

@howmanysmall
Created August 23, 2019 23:00
Show Gist options
  • Save howmanysmall/777d60eaaf5c1425a7940511781db899 to your computer and use it in GitHub Desktop.
Save howmanysmall/777d60eaaf5c1425a7940511781db899 to your computer and use it in GitHub Desktop.
local Janitor = (function()
local Instance_new = Instance.new
local LinkToInstanceIndex = newproxy(false)
local Janitors = setmetatable({}, {__mode = "k"})
local Janitor = {
__index = {CurrentlyCleaning = true};
}
local TypeDefaults = {
["function"] = true;
["RBXScriptConnection"] = "Disconnect";
}
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:Cleanup()
if not self.CurrentlyCleaning then
self.CurrentlyCleaning = nil -- A little trick to exclude the Debouncer from the loop below AND set it to true via __index :)
for Object, MethodName in pairs(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 pairs(this) do
this[Index] = nil
end
Janitors[self] = nil
end
self.CurrentlyCleaning = false
end
end
function Janitor.__index:Destroy()
self:Cleanup()
setmetatable(self, nil)
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()
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
local Thread = coroutine.create(ChangedFunction)
coroutine.resume(Thread, Reference.Value, Reference.Value.Parent)
if AllowMultiple then
self:Add(ManualDisconnect, "Disconnect")
else
self:Add(ManualDisconnect, "Disconnect", LinkToInstanceIndex)
end
return ManualDisconnect
end
return Janitor
end)()
local Obliterator = Janitor.new()
local GuiObject = script.Parent
local function PropertyChanged()
if math.random(5) == 3 then
Obliterator:Cleanup()
end
end
Obliterator:Add(GuiObject:GetPropertyChangedSignal("Position"):Connect(PropertyChanged), "Disconnect")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment