How can I make a proper queue system?

I’ve been trying to make a queue system for my game recently, got it working but not in an efficient way. Let’s say that 4 players enter the queue and there are 3 “servers/cashiers”, the first 3 players get their order and the 4th waits until one of the servers are available. I tried doing that, but only 1 cashier is used at a time. Here’s what I’ve tried doing for the queue:

local prompt = script.Parent
local restaurant = prompt.Parent.Parent
local queue = {}
local ordered = {}
prompt.Triggered:Connect(function(p)
	if not table.find(ordered, p) then
		game.ReplicatedStorage.events.queuePos:FireClient(p, #queue + 1) -- shows the player their current position on the queue
		table.insert(queue, p) -- adds player to queue
		table.insert(ordered, p) -- prevents player from ordering twice at a time
	end
end)

while wait() do
	if queue[1] then
		for _, c in pairs(restaurant.cashiers:GetChildren()) do -- for better understanding, c in this case is the cashier, they all have 2 bools and a controller script, the bools are available (bool) and attending (object
			if c.available.Value then
				c.available.Value = false
				c.attending.Value = queue[1]
				table.remove(queue, 1)
				for i, p in ipairs(queue) do
					game.ReplicatedStorage.events.queuePos:FireClient(p, i)
				end
			end
		end
	end
end

The controller script is the same for all cashiers, and it works perfectly, so the problem is in the queue. Can someone help me?

1 Like

Here is some updated code using an event driven approach.

local prompt = script.Parent
local restaurant = prompt.Parent.Parent
local queue = {}
local ordered = {}

prompt.Triggered:Connect(function(p)
    if not table.find(ordered, p) then
        game.ReplicatedStorage.events.queuePos:FireClient(p, #queue + 1) -- shows the player their current position in the queue
        table.insert(queue, p) -- adds player to the queue
        table.insert(ordered, p) -- prevents player from ordering twice at a time
    end
end)

local function processQueue()
    while #queue > 0 do
        for _, c in pairs(restaurant.cashiers:GetChildren()) do
            if c.available.Value then
                c.available.Value = false
                c.attending.Value = queue[1]
                table.remove(queue, 1)
                for i, p in ipairs(queue) do
                    game.ReplicatedStorage.events.queuePos:FireClient(p, i)
                end
                break -- Exit the loop after assigning a cashier
            end
        end
        task.wait() -- Yield to prevent performance issues
    end
end

game:GetService("RunService").Heartbeat:Connect(processQueue)

1 Like

works perfectly! thank you so much! only did a few tweaks, here is my final script:

local prompt = script.Parent
local running = false
local restaurant = prompt.Parent.Parent
local queue = {}
local ordered = {}
prompt.Triggered:Connect(function(p)
	if not table.find(ordered, p) then
		game.ReplicatedStorage.events.queuePos:FireClient(p, #queue + 1)
		table.insert(queue, p)
		table.insert(ordered, p)
	end
end)

game:GetService("RunService").Heartbeat:Connect(function()
	while #queue > 0 and not running and task.wait() do
		running = true
		for _, c in pairs(restaurant.cashiers:GetChildren()) do
			if c.available.Value then
				c.available.Value = false
				c.attending.Value = queue[1]
				table.remove(queue, 1)
				for i, p in ipairs(queue) do
					game.ReplicatedStorage.events.queuePos:FireClient(p, i)
				end
				running = false
				break
			end
		end
	end
end)
1 Like

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