PreGame Staging Room Best Practice? (how to prevent Drop-Ins once game starts?)

Greetings, I’m hoping someone here can advise on best practices to set up the following user flow:

  1. Upon logging in, users are presented with a match list. They select the match they want to join or may create a new one.

  2. Once they join/create a match users will enter a Pregame staging room where they can chat, select their teams, set game options, etc… and eventually ready up and begin the game.

  3. Once the game starts, I do not want to allow additional users to drop in. So I would like to remove the match from the match list.

The first solution that came to my mind was to update the match label when the match switched over from “pregame” to “game running”. Then I could filter the match list accordingly. But it looks like there isn’t a way to change a match’s label after it is created. Can client-relayed matches even have labels?

I can think of a few other ways to approach this. But I thought I’d post here to see if there were any best practice recommendations for what seems like a pretty common user flow.

Currently my game uses the client-relayed model. I know the matchmaker does not allow drop-ins. But at the moment adding matchmaking or server-authoritative multiplayer seems like overkill. Looking forward to your suggestions!


I found most of the answers I’m looking for in this thread.

1 Like

Thanks for reporting back,
Summary for other people that might find this topic:

If you’re planning on using something of a “room” approach where a player creates a game, and others can see a list of all (public) games and join that game (or lobby) then you would need to extend the Nakama server with some custom RPC code that allows for this.
It would also allow for the option of building in password protected games or things like that.

I might opensource my solution for this once i get it working if there is interest in it.
Did you manage to solve if tor your situation @Mehoo462? and if so, how? what route did you take?

1 Like


I’m still in the early stages of my project. So I mostly wanted to figure this out as part of my big picture architecture and design plans. I haven’t implemented anything yet.

The chief takeaway for me is that the functionality of client-relayed matches is extremely minimal. The server will assign a matchID and broadcast messages to everyone… and that’s it. If you want to do anything more than that you need to implement server-authoritative matches. I guess this makes sense. If you want to the server to store anything at all about your match (such as labels), then you need to set up real a host node and allocate memory on the server.

The server-authoritative structure is a bit intimidating at first, especially if you’re thinking your use case is extremely simple. But it’s worth figuring out. I haven’t implemented much with it yet, but my impression is that it’s immensely powerful and immensely flexible.

When I actually get around to building my match lobby structure my plan is to add a condition in my MatchLoop LUA function that will update the MatchLabel when the game goes from “staging” to “playing.”

Then when I get the match list I will just filter out the ones I don’t want to show according to the label. I might the filtering in the RPC call so I retrieve a filtered list, or I might retrieve the whole list and filter it on the client side, I haven’t decided yet.

The joinAttempt functionality is also interesting, where you can set up conditions to allow users to join, and send a rejection message with a reason if you need to.

The bottom line is, client-relayed matches are useful intermediate step to test your client build, but for any real production solution you’re probably going to need to use Server Authoritative matches. They do a lot more than reconcile gamestate.

Here is a simple match_loop function that will broadcast all the data packets to all the players. Should be useful to anyone who wants doesn’t need to do any server-side management of gamestate but might still need access to some of the other features of Server Authoritative Matches.

function passThrough.match_loop(context, dispatcher, tick, state, messages)
    for _, m in ipairs(messages) do
 return state
1 Like

As I use Golang on a (almost) daily basis, I’ll probably build some authoritative code to create what I’m aiming for, but I plan on going through the examples in the coming week.

The ListMatches API call also allows a query, so if you were to add the state to the match properties, (like the ones used for non-authoritative matches) you’d probably be able to use that so the filtering happens serverside without much hassle, and then you could always create a custom RPC to trigger that property change. whilst keeping the label a constant value as it’s the name of the match.