Reserved servers don't know their own access code

It’s currently impossible for reserved servers to know their own access code (returned by TeleportService:ReserveServer()) without using DataStoreService, MemoryService, or unreliable teleport data.

The game I’m developing has a server browser, and, depending on the place type, servers report their access code for easy access. Unfortunately, servers do not know their access code, so I created a “Fingerprint” system as a hacky workaround. It “stamps” an access code associated with a privateServerId with MemoryStoreService right before teleportation, so when the reserved server starts up it can easily reference its own code.

There are multiple issues with this approach:

  1. MemoryStoreService could be down, resulting in a “dead” (locked, unjoinable) server and all players being booted and rejoined.

  2. This is unnecessary MemoryStoreService usage.

  3. This is just generally hacky and there is much room for error.

If Roblox were to address this issue, it would allow me to create a server browser without the threat of servers becoming “dead”.

12 Likes

Can’t you just do game.PrivateServerId or am I missing something?

Alas, no. PrivateServerIds are not valid access codes. Access codes can only be retrieved from the result of ReserveServer, prior to teleportation/the server’s startup.

1 Like

The only real way to do this is to pass the codes on as teleport data. I think this is a great idea to have servers be able to report their own codes (in server space obviously).

1 Like

Although I do somewhat agree that it’d be nice for servers to be able to know their own access codes with maybe a property that doesn’t replicate across the server/client boundary (only set on the server), I think that the rationale here is a little shaky. Fingerprinting is not hacky for lack of any other way to actually associate a reserved server with an access code.

ReserveServer just issues server tickets at no cost but it doesn’t actually create any servers. Every server can have an instance of it that’s alive when there’s a non-zero number of players in it (JobId does not persist between servers, your clue-in to that idea). They’re designed to be thrown away easily if you don’t need them anymore - yes, the access code and reserved server would still effectively exist, but no instances of it would ever run if you threw away that information.

Server instances aren’t alive when no one is in them, so how this would help you as a developer if this feature was implemented is not entirely clear. The difference between this feature being implemented and the current state is that it would remove developers’ need to track access codes for reporting, so fundamentally this doesn’t remove the “dead server (instance)” issue. You should focus on why you really need this which is that you want to avoid writing that infrastructure yourself and conserve cloud storage space.

It would be nice and convenient but I don’t think it’s necessary. Current methods are strong, supported and built to fit many codebases. I think you underestimate the capacity of MemoryStoreService, the especially-best solution for dealing with matchmaking now, because it looks like it has low numbers, unless you’re speaking from experience and currently see yourself maxing out its capacity frequently including on high traffic days.

4 Likes

I’ve used TeleportData with no issues. It will take the data from the first person who joins the new server rather than using MemoryStoreService.

This approach seems to be really stable in my experience and I’ve found no issues with it so far.

I realize I kind of glossed over why TeleportData was not an option for me in OP. Here are the main reasons:

  1. TeleportData is player-linked, so data passed through it is meant to be related to the player. Failing to do so means you’re not using the API the way it’s meant to be used, which in my opinion provides a reason not to use it like that.

  2. TeleportData is insecure—this I did mention in OP albeit unexpanded upon. According to the documentation, players (exploiters) can spoof their TeleportData, providing a gateway for all kinds of mischief when using TeleportData with essential functions (such as server identity) in mind. I personally cannot take this risk.

  3. Players join the server a while after it’s actual startup, so essential functionalities would only start loading as soon as the player joins whereas it would have started loading prior to the player’s arrival. Since my game probably uses TeleportService more than any front page game, having the shortest possible loading times is as crucial as having a functional game (people have low attention spans nowadays)

If TeleportData works for you, it works for you. Just note, some of these points might apply to you if not now then in the future.

1 Like

There’s some things I think would be important to note about this point. Not to say you’re wrong but just to reinforce a bit.

TeleportData’s insecurity comes from it being transmitted alongside the client given that it’s the client reconstructing a new DataModel when they teleport. If the client performs a teleport then yes they can also specify their own teleport data.

There’s also server-side teleport data though which is surprisingly something that still isn’t very well known. Teleport data specified by a server-performed teleport is server-sided. Roblox provides a guarantee of no tampering for server side data however clients will be able to reuse data from a previous teleport, so there’s a new avenue to think about when that happens.

That being said, you are correct in that TeleportData doesn’t work for your use case, you should never be using it to transmit any important data. It is possible to make teleport data bulletproof but I don’t encourage any novice developer to do it and instead just use MemoryStoreService.

2 Likes

I agree with what you said, however I was referring to more of a single player game where that stuff doesn’t matter. I’m not exactly sure what your use case is, but how would MemoryStoreService even work? I don’t see how it is even possible to use it considering that the server cannot access the reserved server code.

Every reserved server has a PrivateServerId associated with it. When the destination server is reserved, it returns both an access code and the complimentary PrivateServerId. Using MemoryStoreService, I can use the returned PrivateServerId as a key in a map, where the value is the identity (or information) that the destination server needs. When the server starts up, it can grab its info using its PrivateServerId as a key in the same memory store.


Unrelated:

Since writing the OP, I’ve opted out of this approach entirely and instead went for server autonomy. What I mean by this is I’m not using fingerprinting at all anymore; servers will get their required info from player datastores or a permanent PrivateServerId → info datastore. Additionally, codes will no longer be sent to a server browser through MessagingService. This is because the server browser is only a rough estimate of what actually goes on in a server (there is an intentional messaging delay of 10 seconds and messages might fail, resulting in extremely outdated estimates if long-term).

It could happen that a server thinks a server is online since it’s displayed in the server browser, so it sends the player without fingerprinting anything. The server, actually offline, receives the player but no fingerprint so has no choice but to rejoin the player. Thus, I’m now only using the server browser for rough estimates, such as player counts and other non-essential information.

There still might be places I need to fingerprint for, examples being minigames that require some sort of non-essential data that the teleporting server has. I really doubt this would ever happen, but just in case, I’d like to keep fingerprinting in my deck of cards. Servers knowing their own access code would still be great, of course (I’ve found numerous topics expressing their need for this, too), however, I don’t think I would depend on this functionality much if it were ever implemented.

Feel free to grill me on this (I have not updated my codebase yet).

1 Like

Support for this.

We also pass it through TeleportData but it seems like such a needless hack.