KIIS: A faster Roblox BindableEvent System

Hi, I’m 0J3!
Recently I’ve been working on 2 Roblox BindableEvent Alternatives, as “Vanilla” BindableEvents felt a bit slow to me, didn’t have enough features and I felt like it would be a good idea to share these with the rest of the community!

I will be putting both of these in the same post, as they are both pretty similar. They also both should, in theory, work with both Luau and vanilla Lua 5.1, although it is only tested with the former. (Loading the module in Lua5.1 will be different ofc)

KIIS: Keep it insanely simple

KIIS, or Keep It Insanely Simple, is a very simple BindableEvent Alternative, designed for speed, and only speed. No extra features, little-to-no OOP. Here are some benchmark results comparing KIIS to Roblox Vanilla Events:


It is designed purely for speed, and really nothing else.

Example Usage
-- Import KIIS
local KIIS = require(6822873135);

-- Create KIISBindable
local bindable = KIIS.new();
-- Create a connection
local connection1 = bindable:Connect(function()
  print("a");
end);
bindable:Fire();
--> a
local connection2 = bindable:Connect(function()
  print("b");
end);
bindable:Fire();
--> a
--> b

connection1:Disconnect();
-- prevent memory leaks
bindable:GarbageCollect();

bindable:Fire();
--> b
API Docs
KIIS

KIIS.new()

Creates a KIISBindable object

KIISBindable

KIISBindable:Connect(cb)

Creates a KIISConnection Object, with the callback cb. If cb is not a function, it will error when :Fire or :FireAsync are called.

KIISBindable:Disconnect(i)

Disconnects the KIISConnection with the id i. You can get the ID using KIISConnection.ID

KIISBindable:Fire(…any)

Calls all KIISConnection.Callback-s associated with this KIISBindable

KIISBindable:FireAsync(…any)

Alias for KIISBindable:Fire()

KIISBindable:FireSync(…any)

Same as KIISBindable:Fire() except fires synchronously, so if one errors, the rest still get fired, and if one yields, the rest don’t get delayed. Recommended if the connections can yield and/or error, but everything still needs to get fired. This is more similar to vanilla behavior, but is discouraged, due to coroutines (which are what I use to achieve a synchronous function without this issue
If your code isn’t working as expected, or if any of your connections yield, you should use this to fire the bindable.

KIISBindable:GarbageCollect()

Removes any disabled KIISConnections. Please call this occasionally, if you disconnect events.
If you are disconnecting connections at a slow rate, call this after every disconnection.
If you are mass-disconnecting connections, call this after mass-disconnecting.

KIISConnection

KIISConnection:Disconnect()

Disconnects the KIISConnection, clears the .CB value, and sets .Disabled to true.

KIISConnection.Parent

The KIISBindable the KIISConnection is bound to;

Roadmap
  • Add :Destroy() method to KIISConnection

Module

0ES: 0J3’s Event System (Beta)

0J3’s Event System is a slightly more advanced Event System than KIIS, allowing you to re-connect disconnected events, see how often an event was fired, and changing callbacks without connecting again.

It is also faster than vanilla Roblox events, by aprox. 2 times, as shown here:

Example Usage
local eventSystem = require(6822278371);
local event = eventSystem.makeEvent("exampleEvent");

-- Print Event Name
print(event:GetName());
--> exampleEvent

-- Print Event
print(event)
--> Event exampleEvent

-- make a few connections
local connection = event:Connect(function()
  print("b")
end);
for i=1,10,1 do
  event:Connect(function(...)
    print(...)
  end);
end;

-- print some stats
print(event:Stats());
--> Calls: 0
--> Last call At: never

print(event:Stats().calls,event:Stats().lastCallAt);
--> 0, -1

connection:Disconnect();
event:FireSync("a"); -- returns after all connections are done
--> a (x10)

connection:Reconnect();
event:Fire("c"); -- returns more-or-less immediately
--> b
--> c (x10)

for _,o in pairs(event:GetConnections()) do -- loop over connections
  o:SetCb(function() -- set callbacks to a new function
    print("e");
  end);
end;

-- set connection's cb
connection:SetCb(function()
  print("d");
end);

event:Fire();
--> d
--> e (x10)

print(a:Stats().calls, a:Stats().lastCallAt);
--> 7 1621130452
API Docs
OES/OESModule

OES.makeEvent(identifier?:string) => Event

Makes an event, with the optional identifier of identifier. If specified, it should be unique. It can be accessed using Event:GetName();
If identifier is already used, this will render getting it from OES.getEvent(name)

OES.getEvent(name:string) => Event | nil

Returns the event with the identifier name.

OES.isEvent(o:any) => Boolean

Returns true of o is an Event object

OES.isConnection(o:any) => Boolean

Returns true of o is a Connection object

Event/Bindable/OESBindable

Event:Connect(cb:(…any)->nil)

Connects cb to Event

Event:Fire()

Asynchronously fires the Event. See KIIS:FireAsync() for more information.

Event:FireSync()

Synchronously fires the Event. See KIIS:FireSync() for more information.

Event:Stats()

Returns (printable) Table (which’s tostring gives a human-friendly version) containing

  • calls:number > Calls
  • lastCallAt:number > Unix time of last call
  • (Soon) connections:{} > Connections
    → total:number > Total Connection Count
    → connected:number > Amount of connected connections
    → disconnected:number > Amount of disconnected connections

Event:GetConnections()

Returns a Connection[] of connections, where nil indicates a disconnected connection.

Event.ClassName: string

Always “Event”

(Soon) Event:Destroy()

Destroys the event, and all of its connections.

Connection/OESConnection

Connection:Disconnect()

Disconnects a Connection.

Connection:Reconnect()

Reconnects a Connection.

(Soon) Connection:Destroy()

Destroys a Connection.

Connection:SetCb(cb:(…any)->nil)

Sets the Connection's callback to cb;

Connection.Parent: Connection

The Bindable this Connection is parented to

Connection.Active: Boolean

Describes whether a Connection is connected.

Connection.Callback: (…any)->nil

A Connection's Callback - Gets called when Connection.Parent gets fired

Connection.ClassName: string

Always "Connection"

Roadmap
  • Add Connection Count to the :stats() function
  • Add :Destroy() method
  • Maybe add a garbage collector(?)
  • Extension support, to allow you to add functionality to the event system(?)

Module

I hope you find these modules useful, in some way, shape or form.

Thanks for reading,
- 0J3

P.S.

P.S. If you have any issues, feel free to contact me
P.P.S. This is my first Community Resources-related post, so please tell me if I did anything wrong, or missed anything.
P.P.P.S. I was too lazy to switch accounts in studio when publishing the 2 modules, so they are owned by my other account, 0J3_3.
P.P.P.P.S. This project is licensed under the MIT License
P.P.P.P.P.S. this is a lot of P.s

15 Likes

Rojo Support

Hi, 0J3 here again.
I’m proud to announce that, after 2 minutes of reading Rojo documentation, I have added Rojo support for both KIIS and 0ES!

Just copy

into your game’s repository, in the relevant folders (ie /src/shared/lib), and you’ve got KIIS/0ES in your project, or otherwise insert the repository into your Rojo folder.

Thanks for taking time out of your day to read this,
- 0J3

2 Likes

Sync/Async

So I managed to, in both KIIS and 0ES, mess up the names for :FireSync()/:FireAsync() to be the exact opposite of what they are meant to - I have released an update that should fix this. It only renames :FireSync()/:FireAsync(), not :Fire() so your code shouldn’t need to change unless it uses :FireSync()/:FireAsync()

TL;DR:
Git Changes (Image)

Thanks for taking time out of your day to read this
- 0J3

P.S. If you want :Wait(), you can look at the workaround I did in my fork of CutsceneService (It’s dirty, but it works - sorta - and should only be used if you absolutely must)

1 Like