Teleporting players into the same server in a place

Hi there. I have a queue system in which players players queue up to play a 1v1 PVP game. I want my queue system to make sure that it teleports users to the same server in that place.

The queue system works fine, however I stumbled upon the problem that the queue system doesn’t always teleport players to the exact same server. I’ve tried modifying my code using ReservedServers however now my code does not work at all. I’m not getting any errors in the output.

What can I do to fix this code in order to make it teleport users to the right place. Am I using ReserveServer() wrong? Any help would be appreciated, thanks!

local memoryStore = game:GetService("MemoryStoreService")
local queue = memoryStore:GetSortedMap("Queue")
local TeleportService = game:GetService("TeleportService")

local minimum = 2
local maximum = 2

local place = game:GetService("TeleportService"):ReserveServer(15840374569)

local re = game.ReplicatedStorage:WaitForChild("QueueRE")


function addToQueue(player)
	queue:SetAsync(player.UserId, player.UserId, 2592000)
end

function removeFromQueue(player)
	queue:RemoveAsync(player.UserId)
end


local cooldown = {}

re.OnServerEvent:Connect(function(player, inQueue)
	
	if cooldown[player] then return end
	cooldown[player] = true
	
	if inQueue == "In Queue" then
		pcall(addToQueue, player)
	elseif inQueue == "Join Queue" then
		pcall(removeFromQueue, player)
	end
	
	wait(1)
	cooldown[player] = false
end)


game.Players.PlayerRemoving:Connect(removeFromQueue)



local lastOverMin = tick()

while wait(1) do
	
	local success, queuedPlayers = pcall(function()
		return queue:GetRangeAsync(Enum.SortDirection.Descending, maximum)
	end)
	
	if success then
		
		local amountQueued = 0
		
		for i, data in pairs(queuedPlayers) do
			amountQueued += 1
		end
		
		if amountQueued < minimum then
			lastOverMin = tick()
		end
		

		local timeOverMin = tick() - lastOverMin
		
		if timeOverMin >= 2 or amountQueued == maximum then
			
			for i, data in pairs(queuedPlayers) do	
				
				local userId = data.value
				local player = game.Players:GetPlayerByUserId(userId)
				
				if player then
					local success, err = pcall(function()
						TeleportService:TeleportAsync(place, {player})
					end) 
					
					spawn(function()
						if success then
							wait(1)
							pcall(function()
								queue:RemoveAsync(data.key)
							end)
						end
					end)
				end
			end
		end
	end
end
2 Likes

There are a few things I want to mention, but before I get to that, I should address the current issue you’re having.

The problem consists of the method of how you’re teleporting the players. I think it’s the combination of both sending the player’s individually is what’s the issue, and teleporting to that place according to its ID, and not its private code, created by TeleportService:ReserveServer(). The place is being treated like an ID, which just sends them to the place without sending them to an actual reserved place. A reserved place is supposedly a private server reserved for future use. So, instead, you should be using TeleportService:TeleportToPrivateServer(). It does exactly what it should do: Sends them to a private server, with the code of that private server, which is created by ReserveServer. And, you should put all the players into a table, and teleport whoever’s within that table. Here’s how that would look when scripted:

-- Do note, this isn't supposed to be taken as exact. It's a reference of what you should do
-- This was derived from a matchmaking script I've made before in the past

-- Queue.Size - Max players for that queue
-- foundedServer - if the player who's queueing found a queue
for _, info in Queue do
	local code = info.key
	local userIDs = info.value -- userIDs can also be looked at as queue'd players

	if #userIDs >= Queue.Size then
		Queue.Map:RemoveAsync(code)
		continue
	elseif #userIDs + 1 <= Queue.Size and not foundedServer then
		foundedServer = true
		
		table.insert(value, player.UserId)
		print("found server", value)				
		
		Queue.Map:UpdateAsync(code, function(_, sort)	
			return userIDs, sort
		end, 3888000)
		
		if #userIDs >= maximum  then
			task.spawn(function()
				local PlayersToSend = {}
				for _, userId in userIDs do
					local player = Players:GetPlayerByUserId(userId)						
					if player then
						table.insert(PlayersToSend, player)
					end
				end

				TeleportService:TeleportToPrivateServer(place, code, PlayersToSend)
			end)
		end
		
		break
	end
end

The thing I wanted to talk about too is the global variable, place. The ReserveServer should actually be created every time a new queue is made. In the future, assuming you will have a player base, everyone will be teleported to that place no matter what. Since place would be the code of the private server, if that was stored globally within the server, it would teleport every person who gets queued in into the same reserved place each time they queue in.

Instead, you should have the queue store the different codes as keys, and its values be a table of where you can add/remove user IDs.

-- if the player queues in, and there's no open queue for them go into, we'll create a queue for them
-- basically,
if not foundedServer then
    local code = TeleportService:ReserveServer(game.PlaceId)
    print("created server:", code)
    Queue.Map:SetAsync(code, { player.UserId }, 3888000)
end

There’s a post that talks about how to optimally implement this. I think you can find use in it

Other than that, hope this helps and good luck on your project.

2 Likes