Making a function queuing system. Help!

Heya!
I’ve been recently attempting to make a system to queue up the execution of functions, but I can’t get it to work right.

My goal is that I can add a function to a table and the code will execute the functions one by one after the previous function has finished (indicated by a “return true”). It must not prevent other out-of-queue functions from running by being in the way.

The module responsible for making the queues looks like this:

function module.AddToQueue(ID : number, name : string, func)
	local enemy = module.Running[ID]
	if not enemy then warn("wha-") return end

	local queue = enemy[name].Queue
	local index = nil

	if queue[1] then
		index = #queue + 1
	else
		index = 1
	end

	queue[index] = func

	module.RunFromQueue(queue, index)
end 

function module.RunFromQueue(queue, index : number)
	local previous = queue[index-1]
	
	if previous then
		repeat task.wait()

		until previous == true

		queue[index]()
		queue[index] = nil
	else
		queue[index]()
		queue[index] = nil
	end
end

It’s quite self explanatory what every function does.

The other module where I insert functions into the queue looks like this:

local function becomeRandomColor()
		print("started")
		--- code stuff here lololol
		
		task.wait(3)
		warn("done")
		return true
	end
	local function printSomething()
		warn("printed")
		task.wait(5)
		return true
	end
	
	
	abilityHandler.AddToQueue(enemy.ID, script.Name, becomeRandomColor)
	abilityHandler.AddToQueue(enemy.ID, script.Name, printSomething)
	warn("INTERCEPTOR")

My goal is that even though I added the stuff to the queue it should instantly warn “INTERCEPTOR”.
+
The queued functions should still delay each other as shown:

  1. print: “started”
    -wait3-
  2. print: “done”
  3. print: printed

But currently it does the opposite of what it should, it delays functions outside the queue. (so It only warns “INTERCEPTOR” after the 5 second delay from the “printSomething” function has ended)

Help would be greatly appreciated!

seems a few features that I might implement differently, i will suggest it as pseudocode below:
you seem to want push some functions that you like the ‘enemy’ to execute one by one (unless one of the function returns non-true value)

-- init
enemy.Queue = {}

-- add to enemy queue
table.insert(enemy.Queue, func)

-- enemy run from queue
local result = true
while result == true do
	if #enemy.Queue == 0 then
		task.wait()
		continue
	end

	local func = table.remove(enemy.Queue, 1)
	result = func()
end

notice we are mainly working with an array of functions,
so using table.insert and table.remove, we don’t need to manage the index ourselves.
also we rely on func() be blocking

1 Like

But will this prevent my other issue where I don’t want it to prevent other funcs from running?

1 Like

Ok, the thing you suggested partially worked out. The only issue I’ve been facing was that if I have something like this:

task.spawn(function()
		task.wait(4.5)
		print("what")
		abilityHandler.AddToQueue(enemy.ID, script.Name, printSomething)
		warn("a")
	end)
	
	while true do
		task.wait(3)
		print("ran")
		abilityHandler.AddToQueue(enemy.ID, script.Name, becomeRandomColor)
	end

It will only run the loop once and then never again (presumably because of the white loop in the queue handler).

1 Like

FunctionQueue (module script)

local module = {}

local queue = {}

function module.AddToQueue(func)
	table.insert(queue, func)
end

function module.RunFromQueue()
	local result = true
	while result == true do
		if #queue == 0 then
			task.wait()
			continue
		end

		local func = table.remove(queue, 1)
		print("Before execute a function")
		result = func()
		print("After execute a function", result)
	end
end

return module

AddToQueue (Server script)

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

local function becomeRandomColor(funcId)
	print("becomeRandomColor started", funcId)
	task.wait(3)
	print("becomeRandomColor ended", funcId)
	return true
end

local funcId = 1
while true do
	local waitTime = math.random(1, 5)
	print("wait", waitTime)
	task.wait(waitTime)
	print("add to queue", funcId)
	local id = funcId
	funcId += 1
	FunctionQueue.AddToQueue(function()
		return becomeRandomColor(id)
	end)
end

ExecuteQueue (Server script)

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

FunctionQueue.RunFromQueue()

Would it be possible to run the “RunFromQueue” function from the AddToQueue function? I want it to execute after adding something to the queue

the ExecuteQueue script calls to my RunFromQueue, which itself is a while loop which do task.wait() until something is added.
so technically, it is at most a frame delayed after add to queue
is that okay?

okay see if this works

FunctionQueue (module script)

local module = {}

local queue = {}

local func = nil

local function RunFromQueue()
	if func then return end

	local result = true
	while result == true and #queue > 0 do
		func = table.remove(queue, 1)
		print("Before execute a function")
		result = func()
		print("After execute a function", result)
		func = nil
	end
end

function module.AddToQueue(func)
	table.insert(queue, func)
	RunFromQueue()
end

return module

AddToQueue (Server script)

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

local function becomeRandomColor(funcId)
	print("becomeRandomColor started", funcId)
	task.wait(3)
	print("becomeRandomColor ended", funcId)
	return true
end

local funcId = 1
while true do
	local waitTime = math.random(1, 5)
	print("wait", waitTime)
	task.wait(waitTime)
	print("add to queue", funcId)
	local id = funcId
	funcId += 1
	FunctionQueue.AddToQueue(function()
		return becomeRandomColor(id)
	end)
end
1 Like

I’m assuming I would have to add a variable like this for every queue I create?

Your solution works great as far as I can tell!

yes the code i made is for a single queue to demonstrate it should work in your desired way. you will have to pair each queue with a processing func variable

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.