Event Module --Now with 5% more uniqueness

Event Module

Hey everyone, I was messing around with some metatables again and I ended up making this module(its probably pretty useless as compared to the others, but why not post it). Its main feature is the ability to create name spaced events, which eliminates the need to create that nastly Events folder in your Replicated Storage.

– Forewarning – This module probably shouldn’t be used as Event endpoints will not be shown in Replicated Storage, you have been adviced

Functions

Event.Remote(namespace: string)

returns an emulated Remote Event under the given namespace with the functions FireServer, FireAllClients, FireClient, and the Events OnServerEvent, OnClientEvent

Example

-- Script
local Event = require(game:GetService("ReplicatedStorage").Event)

Event.Remote("example").OnServerEvent(function(x)
    print(x)
end)

-- Local Script
local Event = require(game:GetService("ReplicatedStorage").Event)

Event.Remote("example"):FireServer("anything at all")
Event.Remote("test"):FireServer("test") -- Won't trigger anything as nothing is
                                        -- connected to this remote namespace

Event.RemoteFunction(namespace: string)

returns an emulated Remote Function under the given namespace with the functions InvokeServer, InvokeClient, and the Events OnServerInvoke, OnClientInvoke

Example

-- Script
local Event = require(game:GetService("ReplicatedStorage").Event)

Event.Remote("double").OnServerInvoke = function(num)
    return num * 2
end

Event.Remote("triple").OnServerInvoke = function(num)
    return num * 3
end

-- Local Script
local Event = require(game:GetService("ReplicatedStorage").Event)

local out1 = Event.RemoteFunction("double"):InvokeServer(5)
print(out1) -- output: 10

local out2 = Event.RemoteFunction("triple"):InvokeServer(5)
print(out2) -- output: 15

Event.Bindable(namespace: string)

returns an emulated Bindable Function under the given namespace with the function Invoke, and the Event OnInvoke

Example

-- Script
local Event = require(game:GetService("ReplicatedStorage").Event)

local data = "DATA"
Event.Bindable("changeData").Event:Connect(function(value)
    data = value
end)

-- Other Script
local Event = require(game:GetService("ReplicatedStorage").Event)

Event.Bindable("changeData"):Fire("New Data")

Event.BindableFunction(namespace: string)

returns an emulated Bindable Event under the given namespace with the function Fire, and the Event Event

Example

-- Script
local Event = require(game:GetService("ReplicatedStorage").Event)

local data = 2
Event.BindableFunction("get").OnInvoke = function()
    return data
end

-- Other Script
local Event = require(game:GetService("ReplicatedStorage").Event)

local out = Event.BindableFunction("get"):Fire()
print(out) -- output: 2

Caveats

  • The Server has to call require on the module script prior to the client calling require
  • Certain properties like the Parent of a Event Instance is non existant as the script is internally
    only using 1 of each of the events, and not exposing any of its properties directly
  • There is no intellisense/autocomplete on this module since its utilizing metatables, Sorry!

Module

--[[
	Event Module By: @daisyesta101 (MrShowerMan)
]]

local RunService = game:GetService("RunService")

local isServer = RunService:IsServer()
local isClient = RunService:IsClient()

local Event = {}

local RemoteEvent = nil
local RemoteFunction = nil
local BindableEvent = nil
local BindableFunction = nil

if isServer then
	local function create(t)
		local new = Instance.new(t)
		new.Parent = script
		new.Name = t
		return new
	end
	RemoteEvent = create("RemoteEvent")
	RemoteFunction = create("RemoteFunction")
	BindableEvent = create("BindableEvent")
	BindableFunction = create("BindableFunction")
elseif isClient then
	RemoteEvent = script:WaitForChild("RemoteEvent")
	RemoteFunction = script:WaitForChild("RemoteFunction")
	BindableEvent = script:WaitForChild("BindableEvent")
	BindableFunction = script:WaitForChild("BindableFunction")
end

function call(callback)
	return function(t, name)
		if t[name] then
			return t[name]
		end
		
		t[name] = callback(name)
		
		return t[name]
	end
end		

Event.Remote = setmetatable({}, { __call = call(function(name)
	if isServer then
		return {
			OnServerEvent = { 
				Connect = function(_, callback)
					return RemoteEvent.OnServerEvent:Connect(function(player, event, ...)
						if event == name then
							callback(player, ...)
						end
					end)
				end
			},
			FireAllClients = function(_, ...)
				RemoteEvent:FireAllClients(name, ...)
			end,
			FireClient = function(_, client, ...)
				RemoteEvent:FireClient(name, client, ...)
			end,
		}
	elseif isClient then
		return {
			OnClientEvent = { 
				Connect = function(_, callback)
					return RemoteEvent.OnClientEvent:Connect(function(event, ...)
						if event == name then
							callback(...)
						end
					end)
				end
			},
			FireServer	 = function(_, ...)
				RemoteEvent:FireServer(name, ...)
			end,
		}
	end
end) })

Event.Bindable = setmetatable({}, { __call = call(function(name)
	return {
		Event = { 
			Connect = function(_, callback)
				BindableEvent.Event:Connect(function(event, ...)
					if event == name then
						callback(...)
					end
				end)
			end
		},
		Fire = function(_, ...)
			BindableEvent:Fire(name, ...)
		end,
	}
end) })

if isServer then
	RemoteFunction.OnServerInvoke = function(player, name, ...)
		return Event.RemoteFunction(name).OnServerInvoke(...)
	end
elseif isClient then
	RemoteFunction.OnClientInvoke = function(name, ...)
		return Event.RemoteFunction(name).OnClientInvoke(...)
	end
end

Event.RemoteFunction = setmetatable({}, { __call = call(function(name)
	if isServer then
		return {
			OnServerInvoke = function(...) end,
			InvokeClient = function(_, ...)
				return RemoteFunction:InvokeClient(name, ...)
			end,
		}
	elseif isClient then
		return {
			OnClientInvoke = function(...) end,
			InvokeServer = function(_, ...)
				return RemoteFunction:InvokeServer(name, ...)
			end,
		}
	end
end) })

BindableFunction.OnInvoke = function(name, ...)
	return Event.BindableFunction(name).OnInvoke(...)
end

Event.BindableFunction = setmetatable({}, { __call = call(function(name)
	return {
		OnInvoke = function() end,
		Invoke = function(_, ...)
			return BindableFunction:Invoke(name, ...)
		end
	}
end) })

return Event
2 Likes

So why should you use this over actual remotes? I don’t see the advantage, sorry if I missed it.

3 Likes

Its mainly for people that dislike the clutter in the large Event Folder in Replicated Storage as well Rojo users who don’t want to switch between roblox studio and their code editor, other than those purposes its likely best to stick to normal events.

3 Likes