Signal Module V1

Basic Signal V1
I came up with a module that will help you in OOP Coding A simple and useful module compared to its alternatives

This is an oop example prepared to explain the use of the BasicSignal Module:

local BasicSignal = require(script.Parent:WaitForChild("BasicSignal"))

local module = {}
local signalcontroller = BasicSignal.Register("Test",true) 
--the first argument must be a unique ID
--the second variable is true by default

module.ElementAdded = signalcontroller.nct
--.nct is the table containing the functions required for connection and can be used in more than one place.
-- for example (:Connect() , :Once() , :Wait() )
--index is the display name of the connection signal, for example :(Part.Touched)

function module.new(elenemt:{})
	signalcontroller:Fire(5,elenemt)
    --the first variable is the timeout.
    --If the signalling connection is in standby, it waits for this time, if the signalling connection does 
    --not come out of standby, the connection is not sent .

    --the second variable is the data you will send, any type of data or multiple data can be sent.
    -- signalcontroller:Fire(1,ture,false,1,"hi",{})
end

return module

a different sample code to try it out:

local Test = require(game:GetService("ServerScriptService").Test)

task.spawn(function()
	local element = Test.ElementAdded:Wait()
    --If you do not give the wait method a number for the timeout, it will wait forever until the function runs 1 time.
	print("first element added:",element)
end)

task.wait(5)

Test.new({"1",1,2,true})
--once fired, one-time connections will not be fired again and standby connections will stop waiting.

Main methods

  • BasicSignal.Register()
local BasicSignal = require(script.Parent:WaitForChild("BasicSignal"))
BasicSignal.Register(name:string,enabled:boolean) 
-[[ Returns

   {
                    ["Connections"] = {},
                    ["Enabled"] = true,
                    ["Name"] = "Test",
                    ["OneTimedConnections"] = {},
                    ["Running"] = true,
                    ["nct"] = {...}
    } 

-]]
  • BasicSignal:Fire()
local BasicSignal = require(script.Parent:WaitForChild("BasicSignal"))
BasicSignal:Fire(name:string,timeout:number,"hello","world",true) 
--is a function that searches for the signal name you enter and triggers that signal without the management table of that signal.

Signal methods

  • Signal:Fire()
local BasicSignal = require(script.Parent:WaitForChild("BasicSignal"))
local SignalController = BasicSignal.Register(name:string,enabled:boolean)
SignalController:Fire(timeout:number,"hello","world",true)
--triggers the signal triggers and disconnects one-time connections no disconnection with unlimited connections
  • Signal:Pause()
local BasicSignal = require(script.Parent:WaitForChild("BasicSignal"))
local SignalController = BasicSignal.Register(name:string,enabled:boolean)
SignalController:Pause()
--stops the operation of the signal and the waiting time is activated in case the signal is triggered
  • Signal:Resume()
local BasicSignal = require(script.Parent:WaitForChild("BasicSignal"))
local SignalController = BasicSignal.Register(name:string,enabled:boolean)
SignalController:Resume()
--activates the signal if the signal is paused
  • Signal:Disable()
local BasicSignal = require(script.Parent:WaitForChild("BasicSignal"))
local SignalController = BasicSignal.Register(name:string,enabled:boolean)
SignalController:Disable()
--Difference from waiting: signals are ignored without being placed in the waiting queue.
  • Signal:Enable()
local BasicSignal = require(script.Parent:WaitForChild("BasicSignal"))
local SignalController = BasicSignal.Register(name:string,enabled:boolean)
SignalController:Enable()
--activates the signal if the signal is disabled.
  • Signal:Remove()
local BasicSignal = require(script.Parent:WaitForChild("BasicSignal"))
local SignalController = BasicSignal.Register(name:string,enabled:boolean)
SignalController:Remove()
--permanently erases the signal

finally simple examples

local Test = require(script.Parent.Test)

--
local element:RBXScriptConnection = nil

--unlimited connection example
element = Test.ElementAdded:Connect(function(...)
	print("1-element added:",...)
	
	--disconnects the connection
	--element:Disconnect()
end)

--one-time connection example
local element = Test.ElementAdded:Once(function(...)
	print("2-element added:",...)
end)

--pending connection example
task.spawn(function()
	local elements = Test.ElementAdded:Wait()
	--If you do not give the wait method a number for the timeout, it will wait forever until the function runs 1 time.
	print("first element added:",elements)
end)

task.wait(5)

Test.new({"1",1,2,true})

task.wait(1)

Test.new({"1",1,2,true})
--You will get 3 outputs on the first trigger.
--On the second trigger, you will only get output number 1.

image

Download Test Place (57.6 KB)
Download BasicSignal Module (2.7 KB)

:warning:You may encounter some errors
:warning:You are free to correct and publish or improve and publish

1 Like

I noticed your :Wait() doesn’t use coroutine.resume and coroutine.yield which would be more efficient and less bloated. So I made one of my own using them if you’d like to take the :Wait() code for your own aswell.

--!strict
--> Signal Class
local Signal = {}
Signal.__index = Signal

--> Connection Class
local Connection = {}
Connection.__index = Connection

--> Types
export type Connection = {
	index : number,
	signal : Signal,

	Disconnect : (Connection) -> ()
}

export type Signal = {
	Connections : {[number] : (any) -> ()},

	Fire : (Signal, any) -> (),
	Connect : (Signal, callBack : (any) -> ()) -> Connection,
	Once : (Signal, callBack : (any) -> ()) -> (),
	Wait : (Signal, timeout : number) -> (),
}

--> Signal Methods
function Signal:Fire(...)
	for i, v in pairs(self.Connections) do
		v(...)
	end
end

function Signal:Connect(callBack : (any) -> ()) : Connection
	table.insert(self.Connections, callBack)
	local index : number? = table.find(self.Connections, callBack)
	
	return setmetatable({
		index = index,
		signal = self :: Signal
	}, Connection) :: any
end

function Signal:Once(callBack : (any) -> ())
	local connection
	connection = self:Connect(function(...)
		callBack(...)
		connection:Disconnect()
	end)
end

function Signal:Wait()
	local thread = coroutine.running()
	self:Once(function(...)
		coroutine.resume(thread, ...)
	end)
	return coroutine.yield(thread)
end

--> Connection Methods
function Connection:Disconnect()
	table.remove(self.signal.Connections, self.index)
end

--> return
return function() : Signal
	return setmetatable({
		Connections = {}
	}, Signal) :: any
end

Also, here’s an example of usage:

local signal = require(game:GetService('ReplicatedStorage').signal)

local testSignal = signal()

local testConnection = testSignal:Connect(function(number : number)
	print(number)
end)

testSignal:Once(function(number : number) --> prints '5' once
	print(number)
end)

testSignal:Fire(5) --> prints '5'

task.wait(5)

testConnection:Disconnect()

testSignal:Fire(10) --> doesn't print
3 Likes