How to Know When All Players Arrive From a Teleport?

Hey,
I am using the teleport service to teleport a group of players to a reserved server using this code:

ts:TeleportToPrivateServer(123456780, ts:ReserveServer(123456780), game.Players:GetPlayers())

I am wondering how to find out when all players arrive? Would the only method be datastores or is there a different method for this?

1 Like

Have you tried LocalPlayerArrivedFromTeleport?

I am wondering how to detect when every player has arrived, not just the local player.

(If this is on the server)

Ok, here’s how I would do it:

  • Add a Players.PlayerAdded event.

  • Using the teleport data table that you can use with the Teleport Service, fire the server when the client enters. (Set up a debounce to avoid overflow, you only need 1 result)

  • The data should specify the amount of players being sent. (that can be sent once on the host server with a group teleport)

  • If the amount of players having joined == the amount specified in the data, you’re all good to go.

1 Like

I’m not sure if this would work but, under ReserveServer it says it also returns the PrivateServerId.
This could be used for saving the amount of players that should be in that server with said PrivateServerId, and after the number is no longer needed, :RemoveAsync() could be called.
(get private server on the place being teleported to with game.PrivateServerId)

--place where they teleported
local DataStoreService = game:GetService"DataStoreService"
local datastore = DataStoreService:GetDataStore"TemporaryPlayerCountHolder"
local TeleportService = game:GetService"TeleportService"
local id,id2 = TeleportService:ReserveServer(123456780)
local p = game.Players:GetPlayers()
pcall(datastore.SetAsync,datastore,id2,#p)
TeleportService:TeleportToPrivateServer(123456780,id,p)
--place where they are teleported to
local DataStoreService = game:GetService"DataStoreService"
local datastore = DataStoreService:GetDataStore"TemporaryPlayerCountHolder"
local s,res = pcall(datastore.GetAsync,datastore,game.PrivateServerId)
if not s or not res then
    res = 0
end
pcall(datastore.RemoveAsync,datastore,game.PrivateServerId)
--do what you want with the expected amount of players

If the wiki is correct, then the second return value of ReserveServer would take the place of the players table, causing an error.

I’ve actually been having issues with this exact problem in terms of a cross-place party system.

There is no method available to determine when all players of a group arrive from a teleport - you can only account for an individual player locally. You can’t even determine if a player failed to teleport or not (which then makes DataStores somewhat pointless).

You’re going to have to set up a time out window or similar wherein you retrieve a list of players that were teleported to the server and check who’s in the server or not by the end of that time window. The list of players can be from a player’s teleport data, a DataStore or MessagingService.

It’s stupid, I know, but that’s one of the only ways I actually know how to do this. I’m not expecting any support for this either until the engine supports code running at a game level while any of it’s places have a non-zero quantity of instances running.

Do you know why I am getting an error with this?

pcall(datastore:SetAsync(id,#playerList))

It is because you need to have a function in the pcall. Maybe try this:

local success, err = pcall(function()
	datastore:SetAsync(id,#playerList)
end)

This is not how you use a pcall this way. The correct manner would be:

local success, result = pcall(datastore.SetAsync, datastore, #playerList)

You can also use @waterrunner’s code, though technically this isn’t correct usage of it either. Although SetAsync doesn’t return anything which makes this fine, you should avoid throwing away values where you don’t need to as well as any pointless upvalues. Proper code:

local success, result = pcall(function ()
    return datastore:SetAsync(datastore, #playerList)
end)

I personally prefer the former because it’s not wrapping an anonymous function and instead the actual method. The latter also teaches bad habits and borders on spaghetti.

local data
pcall(function ()
    data = dataStore:GetAsync(key)
end) -- Throws away useful success value, bad use of pcalls

-- vs.

local data
local success = pcall(function ()
    data = dataStore:GetAsync(key)
end) -- Often leads to bad organisation and doesn't make use of the purpose of pcall completely

-- vs.

local success, data = pcall(function ()
    return dataStore:GetAsync(key)
end) -- Keeps success value, can use for error handling
3 Likes

Thank you for correcting me on this. I will be using your way of using pcalls from now on as this method seems a lot better.

Thanks!

I definitely find wrapping functions over creating anonymous ones better. The whole point of pcall is to call a function and pass any extra arguments to the function, so it’s best to capitalise on that behaviour. It also helps in terms of readability and maintainability for me personally.

local function A(...)
    print(...)
    return "<-- Some letters"
end

local success, result = pcall(A, "B", "C", "D")
print(success, result)

-- Over this:

local function A(...)
    print(...)
    return "<-- Some letters"
end

local success, result = pcall(function ()
    return A("B", "C", "D") -- Oops! Sometimes developers forget to return anything! They may not know pcall accepts returns either!
end)
print(success, result)

A side note; you can also return more than one value from a pcall.

-- Using an anonymous function since there's no other function to wrap
local success, first, second = pcall(function ()
    return "A", "B"
end)
2 Likes