This module was made out of boredom and need for organization
This is an open sourced module that is used to organize instance events(EX: part.Touched, button.MouseButton1Up, RemoteEvent.OnServerEvent, RunService.Heartbeat, etc) and have more control over them in general. A basic scripting knowledge is highly recommended
Source code for you to copy and paste
Summary
local module = {}
local Players = game:GetService("Players")
local BindedEvents= {
}
local function GetTabForInstanceId(id)
return BindedEvents[id]
end
local function SetTabForInstanceId(id, tab)
BindedEvents[id] = tab
end
local function GetTabForInstance(obj, instanceNameTab)
for _,v in ipairs(instanceNameTab) do
if v.Instance == obj then
return v
end
end
end
local function FindEvent(event, EventsTab)
for i,v in ipairs(EventsTab) do
if v.Event == event then
return v,i
end
end
end
local function FindEventConnection(event, EventsTab)
for i,v in ipairs(EventsTab) do
if v.Event == event then
return v.Connection
end
end
end
local function GetEventFunctionsTab(event, EventsTab)
for i,v in ipairs(EventsTab) do
if v.Event == event then
return v.Functions
end
end
end
local function RunFunction(func,DebugError, ...)--This exucutes "func"
if not DebugError then
coroutine.resume(coroutine.create(func) ,...)
else
coroutine.resume(coroutine.create(function(func,...)
local suc,err = pcall(func,...)
if not suc then
warn("[Instance Event Handler]:", err)
end
end),func,...)
end
end
local function RunFunctions(tab ,...)--This run all the functions in "tab"
for i,v in ipairs(tab.Functions) do
if v.returnSelf then
RunFunction(v.Function, v.DebugError, v.returnTab, ...)
else
RunFunction(v.Function, v.DebugError, ...)
end
end
end
local function CreateEvent(obj:Instance, EventTab, EventType:string, event, ExistingTab)
local tab = ExistingTab or
{
Event = event,
Connection = nil,
Functions = {}
}
EventType = EventType:lower()
if EventType == "normal" then
tab.Connection = obj[event]:Connect(function(...)
RunFunctions(tab,...)
end)
elseif EventType == "property" or EventType == "p" then
tab.Connection = obj:GetPropertyChangedSignal(event):Connect(function(...)
RunFunctions(tab,...)
end)
elseif EventType == "attribute" or EventType == "a" then
tab.Connection = obj:GetAttributeChangedSignal(event):Connect(function(...)
RunFunctions(tab,...)
end)
end
if not ExistingTab then
table.insert(EventTab, tab)
end
return tab.Connection
end
local function UnbindEvent(Key, FunctionsTab)
for i,v in ipairs(FunctionsTab) do
if v.Key == Key then
table.remove(FunctionsTab, i)
return
end
end
end
local function RebindEvent(tab, FunctionsTab)
table.insert(FunctionsTab, tab)
end
function module:BindEvent(id:string, instance:Instance, event:string , Function, returnSelf, EventType:string, DebugError:boolean, key:string)--Main function to create/bind an event
local InstanceIdTab = GetTabForInstanceId(id)
if not InstanceIdTab then
local NewTab =
{
Instance = instance,
Events = {},
}
SetTabForInstanceId(id, NewTab)
end
local Connection = FindEventConnection(event, BindedEvents[id].Events) or CreateEvent(instance, BindedEvents[id].Events, EventType or "Normal" , event)
local EventFunctionsTab = GetEventFunctionsTab(event, BindedEvents[id].Events)
local Key = key or ""..tick()
local FunctionTab = {
Function = Function,
Key = Key,
returnSelf = returnSelf,
DebugError = DebugError,
returnTab = {
Connection = Connection,
Connected = true,
},
}
table.insert(EventFunctionsTab, FunctionTab)
function FunctionTab.returnTab:Unbind()
FunctionTab.returnTab.Connected = nil
UnbindEvent(Key, EventFunctionsTab)
end
function FunctionTab.returnTab:Rebind()
FunctionTab.returnTab.Connected = true
RebindEvent(FunctionTab, EventFunctionsTab)
end
function FunctionTab.returnTab:Destroy()
if FunctionTab.binded then
UnbindEvent(Key, EventFunctionsTab)
end
FunctionTab = nil
end
function FunctionTab.returnTab:SetNewFunction(Function)
FunctionTab.Function = Function
end
function FunctionTab.returnTab:Disconnect()
FunctionTab.returnTab.Connection:Disconnect()
FunctionTab.returnTab.Connected = false
end
function FunctionTab.returnTab:DeleteEvent()
if FunctionTab.returnTab.Connection and FunctionTab.returnTab.Connection.Connected then
FunctionTab.returnTab.Connection:Disconnect()
end
local EventTab,EventIndex = FindEvent(event, BindedEvents[id].Events)
table.remove(BindedEvents[id].Events, EventIndex)
end
return FunctionTab.returnTab,FunctionTab
end
function module:Clear(id:string)--This disconnects all the events that are descendants of "id"
if typeof(id) ~= "string" then return end
for i,v in pairs(BindedEvents) do
if i == id then
local Events = v.Events
if Events then
for j,k in ipairs(Events) do
if k.Connection and k.Connection.Connected then
k.Connection:Disconnect()
end
table.remove(Events, j)
end
end
end
end
return true
end
function module:Debug()--This prints the container of all the event
coroutine.resume(coroutine.create(print), BindedEvents)
end
return module
Explaining the main functions you are able to interact with
Summary
function module:BindEvent(id:string, instance:Instance, event:string , Function, returnSelf:boolean, EventType:string, DebugError:boolean, key:string)
...
end)
Simplification
"id": The id that will be used to store all the events of "instance"
"instance": The instance that will be used for connecting the event
"event": The name of the event that will be connected( Normal → ‘Touched’, ‘OnServerEvent’,‘OnClientEvent’, ‘MouseButton1Up’, ‘ChildAdded’, ‘ChildRemoved’, etc: Property → ‘Name’, ‘Parent’, ‘Transparency’, ‘Color’, ‘Text’, ‘Size’, ‘Position’, etc: Attribute → any attribute of an instance)
"Function": The callback function of the event being created
"returnSelf": indicates whether the table containing the event is passed as the first argument for the callback function
"EventType"(leave nil or nothing for default/Normal event): Indicates the type of of event that is required(nil or nothing->Normal, “property” or “p”->Property, “attribute” or “a”->Attribute)
"DebugError": Indicated whether errors caused by the callback function should be debugged
"Key"(optional): optionally accepts a key to be used instead of automatically creating one(ignore this argument is you don’t plan on manually making a key)
function module:Clear(id:string)--Clears/Disconnects all the events that is a descendant of the "id" and removes all of the events's components
...
end)
Functions from the result of calling module:BindEvent()
function eventObject:Unbind()--Unbind that specific callback function from the event so it can be rebinded later on when needed
...
end)
function eventObject:Rebind()--Re-binds that specific callback function to the event
...
end)
function eventObject:Destroy()--Completely removes that specific callback function from the event when no longer in use
...
end)
function eventObject:SetNewFunction(Function)--Sets the new callback function of this event object to "Function"
...
end)
function eventObject:Disconnect()--Disconnects the actual event that runs all the callback function that is connected to it
...
end)
function eventObject:DeleteEvent()--Disconnects the event and remove all the callback functions that is connected to it, basically deletes the event
...
end)
Example of module usage
If you do decide to give this module a try, please leave some feedbacks on what features I could potentially add. However, if you feel that this module is impractical for usage, please leave a reply on your reason.
Also, feel free to ask any question about the module!
- I will consider using this module
- I will definitely be using this module
- Seems useless
- Creative but impractical to use
- Other(reply)
0 voters