How to create an event in a module?

I was wondering how you would go about creating an event in a module that would be like

Regular Script:

local Module = require(pathtomodule)

Module.OnRan(function(args)
      -- code
end)

I don’t know how I would go about this in a regular module without using bindable events.

if you have any idea please assist me.

2 Likes

Tables (or any value for that matter) returned by ModuleScripts are regular values like any others. There are no special rules:

local module = {}

function module.OnRan(args)
    -- code
end

return module
2 Likes

In the module literally do;


local module = {}

module.OnRan = function()
	
end

return module


I got beaten to it, but both methods should work.

1 Like

Would this be possible with OOP and metatables?

1 Like

Confused by what you mean there, this is usually the OOP structure

local Module = {}
Module.__index = Module

function Module.new(coins)
    local self = setmetatable({}, Module)
    self.Coins = coins
    return self
end

function Module:foo()
    print(self.Coins) --> 500
end

return Module

For example

local NewCoins = Module.new(500)
print(NewCoins:foo())
1 Like

Yeah so what I want is basically like a bindable function where you can do a Function:Connect(function(args) but instead doing this with a module, I am attempting to make it so someone can initialize a prefix for a command and then use a .OnRun() every time that a user runs that command.

image kind of an idea on what i’m attempting to accomplish. I’m not very good at explaining so if there is anything you’re confused on let me know.

Use the colon syntax for function definition if you’d like the self syntax sugar:

function easyCmds:OnRun()
    local prefix = self.prefix
end

self here is a local implicitly assigned to the first argument passed.

yeah but that would only return once called on, I want it to be like a normal function that you would have for say a player enters

game:GetService("Players").PlayerAdded:Connect(function(plr)
print(plr.Name)
end)

but instead of this I want it in a module so like

local Module = require(pathtomodule)
local AdminCommands = Module.init("!")

AdminCommands.OnRun("help", function()
-- code
end)

if that makes sense.

You want OnRun to be an event?

Yes that’s what it is I named it wrong.

1 Like

Use a BindableEvent:

local ranEvent = Instance.new("BindableEvent")
easyCmds.Ran = ranEvent.Event

Connecting to the signal:

easyCmds.Ran:Connect(function(command)
    print(command .. " was ran")
end)

Firing the event:

ranEvent:Fire("help")

Keep the BindableEvent itself private to the ModuleScript as it has the power to fire. Only expose the BindableEvent.Event, which is the object used to make connections.

3 Likes

Do bindableevents allow you to send from the event itself?

Like this:

No. You need to BindableEvent:Fire the event as I demonstrated.

I understand that for in order for this to work I would need to allow the serverscript not the module to tell the module script the name of the command they want to create the event for.

I was trying to do this myself a couple of days ago, and it essentially boils down to creating the event functionality yourself. Here’s a rough version of what you can do.
In the module script:

local Thing={} --this is the module
local Foo={_functions={}} --this is the event
Foo.__index=Foo --make it a metatable

function Foo:Connect(f) --this is the connection event that all events use, taking the function
	table.insert(Foo._functions,f) --adds function to the list
end
function Foo:connect(f) return Foo:Connect(f) end
--this just gives the same function another name
--it's optional support for my barbaric camel casing

function Foo:Fire(currentTime) --this can be used to trigger the event, internally or from another script
	for i,v in pairs(Foo._functions) do
		v(currentTime) --this part calls all of the functions connected
	end
end
Thing.Foo=Foo --add event to module

return Thing

And on the other script:

local Thing=require(game.ReplicatedStorage.Thing) --get the module
function happened(ack) --function to connect, even receives arguments
	print(ack)
end
Thing.Foo:Connect(happened) --connection to the event
wait(3)
Thing.Foo:Fire(tick()) --fire the event

Final result prints the current tick. It’s worth noting that the list of functions is still externally editable, so you’ll just have to hope nobody misuses the module and breaks it.
If you want a challenge, try also implementing event:Wait() and connection:Disconnect() to further emulate Roblox events.

3 Likes

I did something like this once. I can’t remember if I ever finished it. Event:Wait (with coroutines) and Connection:Disconnect are included. I added an extra Signal:DisconnectAll method too.
https://hastebin.com/ebedahixay.txt

I was scrolling through the devforums and found found this by @Crazyman32

7 Likes

Nowadays, I use a more robust Event object!

3 Likes

too complex for me, I was able to accomplish what I wanted to do with your previous code! Thanks :slight_smile:

1 Like