Callbacks to Other Scripts with a Module Script

I want to make a callback in a module script that is fired in other scripts. For example:

-- Normal script waiting for callback
local equation_solver = require(game.ServerScriptService.EquationSolver)

local function graph_complete()
    equation_solver.find_value(1)
end

equation_solver:OnGraphDone(graph_complete)

How would I go about something like this? I haven’t found anything online. Is it even possible? Look forward to seeing your responses, thanks.

Your code sample and explanation of what you’re looking for are slightly confusing (at least to me they are), but if you want to achieve something like this, I would recommend using a BindableEvent.

Within the table you return, you’ll have a key which is the name of the event and a value which references BindableEvent.Event. From here, other scripts can connect to the Event of BindableEvent and internally your functions would fire the BindableEvent along with any arguments.

This describes more of an event-based network, though is this about what you’re looking for?

Could you give me an example of what you mean?

Sure. The idea is that you’re using a BindableEvent to facilitate a signal-like backend. Just a reminder that this will not replicate unlike Roblox signals (sadly, because we do not have selective replication). As well, the syntax differs from your code sample in that it uses a dot over a colon.

-- From your ModuleScript:
local module = {}

module.eOnSomethingDone = Instance.new("BindableEvent")
module.OnSomethingDone = module.eOnSomethingDone.Event

function module:DoSomething()
    print("Did something")
    self.eOnSomethingDone:Fire("foo")
end

return module

-- From your other script:
local module = require(module)

local function onSomethingDone(result)
    print(result)
end

module.OnSomethingDone:Connect(onSomethingDone)

Thank you, I will try this out and get back to you. I think this is exactly what I was looking for.

Ok I get the idea of it and why it should work but for some reason it doesn’t. Here’s my module (I return it in equation:draw() after the for loop is done):

local equation = {}

equation.OnGraphDoneEvent = Instance.new("BindableEvent")
equation.OnGraphDone = equation.OnGraphDoneEvent.Event

local Settings = {	
	["EquationType"] = {
		["Linear"] = "linear",
		["Quadratic"] = "quadratic",
		["Sin"] = "sin"
	}	
}

function equation:solve_bc(n1, n2, n_1, n_2)
	local difference = n2 - n1
	local approx = n1 - difference
	local b = difference
	local c = approx
	return b, c
end

function equation:find_value(value)
	local equation_graph = game.Workspace.EquationGraph
	for i,v in pairs(equation_graph:GetChildren()) do
		if v:IsA("Part") then
			if v.Position.Y == value then
				local beam_node = Instance.new("Part")
				beam_node.Size = Vector3.new(1, 1000, 1)
				beam_node.BrickColor = BrickColor.new("Bright red")
				beam_node.Position = v.Position
				beam_node.Anchored = true
				beam_node.Parent = equation_graph
			end
		end
	end
end

function equation:draw(equation)
	local equation_graph = game.Workspace.EquationGraph
	for i,v in pairs(equation_graph:GetChildren()) do
		if v:IsA("Part") then
			v:Destroy()
		end
	end
	if equation[1] == Settings.EquationType.Linear then
		for i = -10, 10, 0.1 do
			local new_node = Instance.new("Part")
			new_node.Size = Vector3.new(1,1,1)
			new_node.Anchored = true
			local x = (i)
			local y = ((i * equation[2]) + equation[3])
			new_node.Position = Vector3.new(x, y, 0)
			new_node.Parent = equation_graph
		end
		self.OnGraphDoneEvent:Fire()
	elseif equation[1] == Settings.EquationType.Quadratic then
		for i = -10, 10, 0.1 do
			local new_node = Instance.new("Part")
			new_node.Size = Vector3.new(1,1,1)
			new_node.Anchored = true
			local x = (i)
			local y = (((i^2) * equation[2]) + (i * equation[3]) + equation[4])
			print(x, y)
			new_node.Position = Vector3.new(x, y, 0)
			new_node.Parent = equation_graph
		end
		self.OnGraphDoneEvent:Fire()
	elseif equation[1] == Settings.EquationType.Sin then
		for i = equation[2], equation[3], 0.5 do
			local new_node = Instance.new("Part")
			new_node.Size = Vector3.new(1,1,1)
			new_node.Anchored = true
			local x = (i)
			local y = math.ceil(math.floor(math.sin(i * math.pi/180) * equation[4] * 100000)/100000 * 1000)/1000
			print(x, y)
			new_node.Position = Vector3.new(x, y, 0)
			new_node.Parent = equation_graph
		end
		self.OnGraphDoneEvent:Fire("foo")
	end
end

function equation:solve(equation_type, n1, n2, n3)
	if equation_type == Settings.EquationType.Linear then
		local difference = n2 - n1
		local approx = n1 - difference
		local plus_or_minus = nil
		if approx < 0 then
			plus_or_minus = ""
		else
			plus_or_minus = "+"
		end
		return {equation_type, difference, approx}
	elseif equation_type == Settings.EquationType.Quadratic then
		local difference_1 = n2 - n1
		local difference_2 = n3 - n2
		local a = (difference_2 - difference_1)/2
		local n_1 = a * 1^2
		local n_2 = a * 2^2
		local term_1 = n1 - n_1
		local term_2 = n2 - n_2
		local b, c = equation.solve_bc(term_1, term_2, n1, n2)
		local pom_b = ""
		local pom_c = ""
		if b > 0 then
			pom_b = "+"
		end
		if c > 0 then
			pom_c = "+"
		end
		return {equation_type, a, b, c}
	end
end

return equation

This is the script:

local equation_solver = require(game.ServerScriptService.EquationModule)

--[[
	equation_solver.solve("linear", 1, 2),
	equation_solver.solve("linear", 7, 15),
	equation_solver.solve("linear", 6, 9),
	equation_solver.solve("quadratic", 7, 9, 12),
	equation_solver.solve("quadratic", 1, 2, 4),
	{"sin", -180, 180, 10},
	{"sin", -180, 180, 3},
	{"sin", -180, 180, 5},
	{"sin", -180, 180, 100}
	]]--

wait(5)

local equations = {
	
	{"sin", -180, 180, 1},

}

local function solve_equation(result)
	print(result)
end

for i,v in pairs(equations) do
	print(table.concat(v, " "))
	equation_solver:draw(v)
end

equation_solver.OnGraphDone:Connect(solve_equation)

After fiddling around with the ModuleScript a bit and both some print work and small reconfigurations, I noticed something: the issue you’re facing here is the time of arrival of these events.

Remember that Lua is single-threaded and runs sequentially. In your case, what’s happening is that you’re connecting to the event after the for loop runs. It connects after the loop runs and the signal fires, so the listener doesn’t ever get to handle the value.

Simply move your event connection below solve_equation to resolve the issue.

local function solve_equation(result)
	print(result)
end

equation_solver.OnGraphDone:Connect(solve_equation)

-- For loop here

Oh wow that really was the problem, it works perfectly now. Thank you so much!