Add ability to pass initial data to server when using ReserveServer

As a Roblox developer, it is currently very difficult to pass initial data to the server you are teleporting players in to.

Right now, I have a lobby system set up and once a lobby fills up, it teleports players to a reserved server (created using TeleportService:ReserveServer(PLACE_ID)). In this server, we require key information in order to start the game: for example, the mode, the map name, teams, etc.

Our current workaround is using TeleportService:TeleportToPrivateServer() and passing in the information we need in the teleportData parameter. In the server that players are teleporting into, we

  1. Wait until the first player joins the server
  2. Get their teleport data
  3. Retrieve the map name from the teleport data (ex. TeleportData.Map)
  4. Finally load in the map

There are two issues with this:

  1. The data is not guaranteed to be safe as it is transmitted alongside the client.
  2. We can’t have the server start loading stuff in until a player joins.

If Roblox is able to pass in optional arguments when calling TeleportService:ReserveServer(), it would allow developers to rely on passing data between teleports securely and it would allow a cleaner implementation of scenarios where we need to know certain data before we can start the game.

13 Likes

I think there will be people who shoot this down due to the recent addition of server sided access to teleport data.

However, I very much agree with this request, currently using teleport data is really a hack. This is a bad way to send data because its insecure, unreliable, and slow, resulting in having to waste extra resources on improving security and reliability.

I can’t trust the data a client sends because if a client reuses teleport data they could forge matches with other players and make the server think they won against them resulting in exploiters being able to lower people’s scores over and over while increasing their own.

Currently, the way I handle this in my game is to send the data per each player, with a timestamp (so I can let the entry data expire to mitigate exploitation). I additionally support the ability to generate salted hashes of the data on the server for more secure verification, and, the salts can be randomized and synced by time.

The problem is why is this up to me? And, it seems hacky and slow to do this.

For reliability, I have to include teleport data for every player, and, whoever is the first to join is the one to pass the data along to the server. But, the server is usually up for a good 10 seconds before this point because people have slower connections.

That 10 second window is well long enough for me to generate the entire map on the server and have everything in the game ready, rather than having a loading screen in their face for even longer than they already waited. Load times in total can be up to like 40 seconds if my connection is slow and I’m joining alone, but, I could cut that down to being 5 seconds if I could transmit start up data directly.

Having a way to pass data to a server that’s being reserved would solve all of my concerns around exploitation, and allow me to make servers start faster.

5 Likes

Use cases like this are what ephemeral DataStores are intended to resolve. They are like DataStores however the data given to them is temporary. This means completely server-sided access to match data and being able to preset it before sending players to the server.

They aren’t currently in the roadmap so I’m not sure if they’ve been renamed or removed completely due to being infeasible. I’m going to assume Memory Store is that feature but with more improvements than being DataStores with an expiry on the data written to them.

2 Likes

Along with an access code, ReserveServer returns the PrivateServerId of the newly reserved server. You can use this to securely transfer data from one to the other without relying on the client and you can access it straight away.

Here’s an example of what you might do. In the origin server you would do the following:

local accessCode, privateServerId = TeleportService:ReserveServer(placeId)

local dataStore = DataStoreService:GetDataStore("ServerData", placeId)

dataStore:SetAsync(privateServerId, newServerData)

-- invoke teleport

Then in the destination server:

local privateServerId = game.PrivateServerId
local placeId = game.PlaceId

local dataStore = DataStoreService:GetDataStore("ServerData", placeId)

local newServerData = dataStore:GetAsync(privateServerId)

-- do something with the data

You can find out more here: [Live] Changes to ReserveServer

3 Likes

Ooh interesting! This looks like it would work great. Thanks!

just wanted to add on to these comments - y’all are quite knowledgeable!

the trouble with join data is exactly that - the client could be compromised, so ideally the solution would be to use something that we offer on our own backend, e.g. Datastores. the code provided above would absolutely work, the caveat I would add is that the data would not be automatically cleaned up, so I might recommend including a timestamp of when the server was reserved then having some kind of tool or process to clean it up after some time.

also, we absolutely do have ephemeral data stores coming soon! it’s been renamed to MemoryStore, and we plan on announcing more details about it. stay tuned.

15 Likes