Authoritative Multiplayer & Matchmaking

Hi,

To start with (I a m happy to have this policy )

we have a “no stupid questions policy” so feel free to ask the community for help.

My questions are :
//-------------------------------------------------
1. if my game require 4 player and a player is matchmaked but did not join. 3 players joined the match already. I assume they have to wait for him. but while waiting the loop_match is executing and players are able to sendMessages (I tested it )

  • My current solution is to make if stalemate at the start of the match_loop

if state.game.allPlayersJoined == true then
// do stuff here
end

and state.game.allPlayersJoined will be true only if 4 players joined the match … then I will start. Is this approach is correct and the smartest one?
//-------------------------------------------------
2. According to question 1 what if the 4th player did not want to joint at all. How to bring another player to the match (make it available on matchmaking) ? How much time the 4th player have as a chance to join?

docs (matchmaker tokens)

Tokens are short-lived and must be used to join a match as soon as possible. When a token expires it can no longer be used or refreshed.

//-------------------------------------------------
3. for match_join (context, dispatcher, tick, state, presences)
I am concerned about presences, this means more than one presence (duh from the s :grimacing:), also from docs …

presences —> (table) —> Presences is a list of users that have joined the match.

but I notice that when I print all the presence

for _, presence in ipairs(presences) do
print …
end

It always only print one presence at a time (I tried to join a simple game from two devices to test this)
So is it possible that you will get more than one presence and when???
//----------------------------------------------------
4. for the match_leave(context, dispatcher, tick, state, presences)
from doc is says

– Executed when one or more users have left the match for any reason including connection loss.

So In my case I want to make leave button on the game —> if player clicked it then he will lose
but I don’t want to make him leave (lose the game) if the game is closed or get a call or lost connection . Any ideas how to distinguish between scenarios?
And how the player can resume to that game?
//----------------------------------------------------

Hey. We’ll help with as many questions as we can. :slight_smile:

1. if my game require 4 player and a player is matchmaked but did not join. 3 players joined the match already. I assume they have to wait for him. but while waiting the loop_match is executing and players are able to sendMessages (I tested it ) […snip…] and state.game.allPlayersJoined will be true only if 4 players joined the match … then I will start. Is this approach is correct and the smartest one?

This is one way to solve the problem but remember that the fourth player may never join so you’ll have a match stuck that cannot start because it waits for the other players to join in your code. Although if you use match listings for players to find matches to join after then you could keep the match in this state of “waiting” for a while.

Another way to handle the use case is to track the amount of time (logical ticks in the match loop) before you declare that the match must start without the extra player(s) or send a message to have players drop back to the matchmaker to play again. The option you choose will depend on what makes most sense to your game design.

2. According to question 1 what if the 4th player did not want to joint at all. How to bring another player to the match (make it available on matchmaking) ? How much time the 4th player have as a chance to join?

I think I’ve answered this above but can add more detail if it’d be helpful.

3 . for match_join (context, dispatcher, tick, state, presences )
I am concerned about presences , this means more than one presence (duh from the s), also from docs … […snip…] It always only print one presence at a time (I tried to join a simple game from two devices to test this) So is it possible that you will get more than one presence and when???

You can receive more than one presence when the time between one tick and the next has more than one player join the match. i.e. very very fast concurrent joins by multiple players.

This is not a problem because you’ve got all the information you need in the datastructures to add the presences to how you want to track them in your multiplayer match. Just have your code handle if more than one presence comes in at once.

So In my case I want to make leave button on the game —> if player clicked it then he will lose
but I don’t want to make him leave (lose the game) if the game is closed or get a call or lost connection . Any ideas how to distinguish between scenarios?

The match leave lifecycle event will always be called with the presence of the player that has been disconnected. You should use this event to clear up the state of the player in the match handler but you could also mark a timestamp (tick number) against the presence you track in your match state to indicate that the player is marked as left. Then remove the timestamp if they come back.

And how the player can resume to that game?

The player can always rejoin with the match ID which you get back when they’ve joined.

Thank you @novabyte

But I have one more question regarding question 3

you can receive more than one presence when the time between one tick and the next has more than one player join the match. i.e. very very fast concurrent joins by multiple players.

but why M.match_join_attempt receives only one presence, even though it is been triggered more than match_join . (I really can ignore this and carry on my work but it will always make me think about it before sleeping because it doesn’t make sense to me :sweat:)

oops and one more question for Question 4
Still not clear for me how to identify if the players

  • Click leave or exit ==> so I can remove him from the match and mark his profile that he lost the match

  • Lost the internet connection or accidentally closed the game ==> so I will mark a timestamp (tick number) against the presence so maybe give him some time to come back so he can resume

but why M.match_join_attempt receives only one presence, even though it is been triggered more than match_join.

They serve different purposes which is why they have different function signatures in a match handler in the authoritative multiplayer engine.

The match join attempt function is used to individually decide whether a presence is allowed to join the match. We use a queue datastructure to ensure that these events are processed in sequence. When presences are accepted to join they can end up concurrently acting in between one execution of the match loop and the next so they’ll be batched into the match join function.

I’m happy to explain why these functions are different but how does it affect your game development? They’re quite clear to use and the API has been carefully designed to ensure that authoritative multiplayer is as straightforward as possible to use within Nakama.

Still not clear for me how to identify if the players

You don’t need to identify them differently. Both situations can leave a marker next to the player’s presence in your data structure. If you really do want to decide that a player can choose to “leave” then before you use the MatchLeave API function from your game client send a message to the match handler that indicates the leave was done as a player action.