Help on queue system

I need help fixing my queue system. Problems I have encountered was that even though it displays that there are “10 / 10” players, it doesn’t seem to teleport them. Before I added a check to check if the player is the leader, it would teleport the players but all of them having different reserved servers. It also sometimes teleports players into the server but only like 4 of them would make it.

Queue code:

local module = {}

local MemoryStoreService = game:GetService("MemoryStoreService")
local Queue = MemoryStoreService:GetSortedMap("Queue")
local PartyStore = MemoryStoreService:GetSortedMap("PartyStore")

local TeleportService = game:GetService("TeleportService")
local MessagingService = game:GetService("MessagingService")

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Remotes = ReplicatedStorage:WaitForChild("Remotes")

local QueuesData = require(script:WaitForChild("QueuesData")) -- contains info like place id, min players, and max players

local expirationTime = 1000
local waitTime = 10
local delayTime = 3

local connections = {}

function module.LeaveQueue(player)
	if connections[player] then
		task.cancel(connections[player])
		connections[player] = nil
	end

	local success, err = pcall(function()
		return Queue:RemoveAsync(player.UserId)
	end)

	if success then
		print(player.Name.." left the queue")
		return true
	else
		warn(player.Name.." Failed to exit queue: "..err)
	end
end

function module.InQueue(player)
	local success, queuedData = pcall(function()
		return Queue:GetAsync(player.UserId)
	end)

	if success and queuedData then
		return true
	end
end

function module.StorePartyData(player, party)
	local playerId = player.UserId

	local success, err = pcall(function()
		PartyStore:SetAsync(tostring(playerId), playerId, expirationTime)
	end)

	for _, member in ipairs(party) do
		local memberPlayer = game.Players:FindFirstChild(member.Name)

		if memberPlayer then
			local success, err = pcall(function()
				PartyStore:SetAsync(tostring(member.UserId), playerId, expirationTime)
			end)

			if not success then
				warn("Failed to store party data: "..err)
			end
		end
	end
end

function module.CheckQueue(player, party, queueData)
	local currentTime = tick()

	local placeId = queueData.PlaceId
	local minPlayers = queueData.MinPlayers
	local maxPlayers = queueData.MaxPlayers

	module.StorePartyData(player, party)

	connections[player] = coroutine.create(function()
		while task.wait(1) do
			local success, queuedPlayers = pcall(function()
				return Queue:GetRangeAsync(Enum.SortDirection.Descending, maxPlayers)
			end)

			if success then
				local alreadyQueued = {}

				for _, playerData in ipairs(queuedPlayers) do
					alreadyQueued[playerData.value] = true
				end

				for _, member in ipairs(party) do
					if not alreadyQueued[member.UserId] then
						local data = {["key"] = member.UserId, ["value"] = member.UserId}
						table.insert(queuedPlayers, data)
					end
				end

				local amountQueued = #queuedPlayers

				if amountQueued < minPlayers then
					currentTime = tick()
				end

				print("Queued players: "..amountQueued.." / "..maxPlayers)

				player.PlayersQueued.MaxValue = maxPlayers
				player.PlayersQueued.Value = amountQueued

				pcall(function()
					for _, member in ipairs(party) do
						member.PlayersQueued.MaxValue = maxPlayers
						member.PlayersQueued.Value = amountQueued
					end
				end)

				local waitingTime = tick() - currentTime

				if waitingTime >= waitTime or amountQueued == maxPlayers then
					local leaderId = queuedPlayers[1].value
					
					print(leaderId)

					if player.UserId == leaderId then
						local reservedServerCode

						local success, result = pcall(function()
							reservedServerCode = TeleportService:ReserveServer(placeId)
						end)

						if success then
							local dataToSend = {
								Message = "Ready",
								AccessCode = reservedServerCode,
								PlaceId = placeId,
							}

							for _, data in ipairs(queuedPlayers) do
								local userId = data.value
								MessagingService:PublishAsync(userId, dataToSend)
							end
						else
							warn("Failed to reserve server: "..result)
						end
					end
				end
			end
		end
	end)

	coroutine.resume(connections[player])
end

function module.Queue(player, party, queueType)
	if not module.InQueue(player) then
		module.LeaveQueue(player)

		local queueData = QueuesData[queueType]

		if queueData then
			local success, err = pcall(function()
				return Queue:SetAsync(player.UserId, player.UserId, expirationTime)
			end)

			if success then
				print(player.Name.." Successfully queued!")

				module.CheckQueue(player, party, queueData)

				return true
			else
				warn(player.Name.." Failed to queue: "..tostring(err))
			end
		end
	else
		warn(player.Name.." is already in queue")
	end
end

game.Players.PlayerAdded:Connect(function(player)
	local connection

	local success, err = pcall(function()
		connection = MessagingService:SubscribeAsync(player.UserId, function(callback)
			local data = callback.Data
			Remotes.Queue:FireClient(player, "Ready")

			if data and data.Message == "Ready" then
				connection:Disconnect()

				print("Teleporting...")

				local TeleportOptions = Instance.new("TeleportOptions")
				TeleportOptions.ReservedServerAccessCode = data.AccessCode

				local retries = 3
				local success, errorMessage

				repeat
					success, errorMessage = pcall(function()
						TeleportService:TeleportAsync(data.PlaceId, {player}, TeleportOptions)
					end)

					retries -= 1
				until success or retries == 0

				if success then
					print("Teleportation successful")

					module.LeaveQueue(player)

					return true
				else
					warn("Failed to teleport players: "..tostring(errorMessage))
				end
			end
		end)
	end)
end)

return module
1 Like

I managed to solve it by rewriting most parts and using DataStoreService to store the leader.

1 Like

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