|
1 | | -Contains the online matchmaker. |
| 1 | +# Matchmaking |
2 | 2 |
|
3 | | -## Matchmaking |
| 3 | +For online matchmaking, we use a centralized matchmaking server to connect peers to each-other and to forward the peers' network traffic. All connections utilize UDP and the QUIC protocol. |
4 | 4 |
|
5 | | -For online matchmaking, we use a centralized matchmaking server to connect peers to each-other and |
6 | | -to forward the peers' network traffic. All connections utilize UDP and the QUIC protocol. |
| 5 | +The matchmaking server is implemented in the [`bones_matchmaker`] crate. It binds to a single UDP port and listens for client connections. QUIC's multiplexing capabilities allow the server to handle any number of clients on this single port. |
7 | 6 |
|
8 | | -In order to establish the peer connections we use a matchmaking server implemented in the |
9 | | -[`bones_matchmaker`] crate. This server binds one UDP port and listens for client connections. |
10 | | -Because QUIC supports mutliplexing connections, we are able to handle any number of clients on a |
11 | | -single UDP port. |
| 7 | +Once a match starts, client traffic is proxied through the matchmaking server. While not true peer-to-peer networking, clients logically send messages to each other, with the server acting as an intermediary. |
12 | 8 |
|
13 | | -All client traffic is proxied to other peers through the matchmaking server. In this way it is not |
14 | | -true peer-to-peer networking, but logically, once the match starts, clients are sending messages to |
15 | | -each-other, and the server doesn't take part in the match protocol. |
| 9 | +Pros of this approach: |
| 10 | +- Reduced connections per peer (one connection to the matchmaker only) |
| 11 | +- Client IP addresses are hidden from each other |
| 12 | +- Easier to bypass firewalls and NATs |
| 13 | +- Simplified connection process |
16 | 14 |
|
17 | | -Having the matchmaker proxy client messages has the following pros and cons: |
| 15 | +Cons: |
| 16 | +- Increased server bandwidth usage |
| 17 | +- Additional network hop between peers, potentially increasing latency |
18 | 18 |
|
19 | | -**Cons:** |
20 | | - |
21 | | -- It uses up more of the matchmaking server's bandwidth |
22 | | -- It adds an extra network hop between peers, increasing latency. |
23 | | - |
24 | | -**Pros:** |
25 | | - |
26 | | -- It reduces the number of connections each peer needs to make. Each peer only holds one |
27 | | - connection to the matchmaking server and nothing else. |
28 | | -- It hides the IP addresses of clients from each-other. This is an important privacy feature. |
29 | | -- It avoids a number of difficulties that you may run into while trying to establish true |
30 | | - peer-to-peer connections, and makes it much easier to bypass firewalls, NATs, etc. |
31 | | - |
32 | | -This doesn't prevent us from supporting true peer-to-peer connections in the future, though. |
33 | | -Similarly, another scenario we will support in the future is LAN games that you can join without |
34 | | -needing a matchmaking server. |
| 19 | +This design doesn't preclude future support for true peer-to-peer connections or LAN games without a matchmaker. |
35 | 20 |
|
36 | 21 | [`bones_matchmaker`]: https://github.com/fishfolk/bones/tree/main/crates/bones_matchmaker |
37 | 22 |
|
38 | | -### Matchmaking Protocol |
39 | | - |
40 | | -> **ℹ️ Note:** This is meant as an overview and is not an exact specification of the matchmaking |
41 | | -> protocol. |
42 | | -
|
43 | | -#### Initial Connection |
44 | | - |
45 | | -When a client connects to the matchmaking server, the very first thing it will do is send a |
46 | | -[`RequestMatch`][crate::external::bones_matchmaker_proto::MatchmakerRequest::RequestMatch] message |
47 | | -to the server over a reliable channel. |
48 | | - |
49 | | -This message contains the [`MatchInfo`] that tells the server how many players the client wants to |
50 | | -connect to for the match, along with an arbitrary byte sequence for the `match_data`. |
51 | | - |
52 | | -In order for players to end up in the same match as each-other, they must specify the _exact_ same |
53 | | -`MatchInfo`, including the `match_data`. We use the `match_data` as a way to specify which game mode |
54 | | -and parameters, etc. that the player wants to connect to, so that all the players that are connected |
55 | | -to each-other are playing the same mode. |
56 | | - |
57 | | -The `match_data` also contains the game name and version. Because the matchmaker does not take part |
58 | | -in the match protocol itself, just the matchmaking protocol, **this makes the matchmaking server |
59 | | -game agnostic**. Different games can connect to the same matchmaking server, and they can make sure |
60 | | -they are only connected to players playing the same game, by specifying a unique `match_data`. |
61 | | - |
62 | | -> **Note:** To be clear, the game implementation sets the `match_data` for players. Players are |
63 | | -> never exposed directly to the concept of the `match_data`. |
| 23 | +## Matchmaking Protocol |
64 | 24 |
|
65 | | -#### Waiting For Players |
| 25 | +### Initial Connection |
66 | 26 |
|
67 | | -After the initial connection and match request, the server will send the client an |
68 | | -[`Accepted`][crate::external::bones_matchmaker_proto::MatchmakerResponse::Accepted] message. |
| 27 | +1. The client connects to the matchmaking server. |
| 28 | +2. The client sends a [`RequestMatchmaking`][crate::external::bones_matchmaker_proto::MatchmakerRequest::RequestMatchmaking] message over a reliable channel. |
| 29 | +3. This message contains [`MatchInfo`] with: |
| 30 | + - The desired number of players |
| 31 | + - A `game_id` to identify the game |
| 32 | + - `match_data` (arbitrary bytes for game mode, parameters, etc.) |
| 33 | + - `player_idx_assignment` to specify how player ids should be assigned (ie. randomly assign a side for a pvp match) |
69 | 34 |
|
70 | | -If the waiting room for that match already has the desired number of players in it, the server will |
71 | | -then respond immediately with a |
72 | | -[`Success`][crate::external::bones_matchmaker_proto::MatchmakerResponse::Success] message. This |
73 | | -message comes with: |
| 35 | +Players must specify identical `MatchInfo` to be matched together. The `match_data` ensures players are connected for the same game mode and version. |
74 | 36 |
|
75 | | -- a `random_seed` that can be used by all clients to generate deterministic random numbers, and |
76 | | -- a `player_idx` that tells the client _which_ player in the match it is. This is used throughout |
77 | | - the game to keep track of the players, and is between `0` and `player_count - 1`. |
| 37 | +### Waiting for Players |
78 | 38 |
|
79 | | -#### In the Match |
| 39 | +1. The server responds with an [`Accepted`][crate::external::bones_matchmaker_proto::MatchmakerResponse::Accepted] message. |
| 40 | +2. While waiting, the server may send [`MatchmakingUpdate`][crate::external::bones_matchmaker_proto::MatchmakerResponse::MatchmakingUpdate] messages with the current player count. |
| 41 | +3. When the desired number of players is reached, the server sends a [`Success`][crate::external::bones_matchmaker_proto::MatchmakerResponse::Success] message containing: |
| 42 | + - A `random_seed` for deterministic random number generation |
| 43 | + - The client's `player_idx` |
| 44 | + - The total `player_count` |
| 45 | + - A list of `player_ids` with their network addresses |
80 | 46 |
|
81 | | -Immediately after the desired number of clients have joined and the `Success` message has been sent |
82 | | -to all players, the matchmaker goes into proxy mode for all clients in the match. |
| 47 | +### In the Match |
83 | 48 |
|
84 | | -Once in proxy mode, the server listens for |
85 | | -[`SendProxyMessage`][crate::external::bones_matchmaker_proto::SendProxyMessage]s from clients. Each |
86 | | -message simply specifies a [`TargetClient`][crate::external::bones_matchmaker_proto::TargetClient] ( |
87 | | -either a specific client or all of them ), and a binary message data. |
| 49 | +Once all players have received the `Success` message, the matchmaker enters proxy mode: |
88 | 50 |
|
89 | | -Once it a `SendProxyMessage` it will send it to the target client, which will receive it in the form |
90 | | -of a [`RecvProxyMessage`][crate::external::bones_matchmaker_proto::RecvProxyMessage], containing the |
91 | | -message data, and the index of the client that sent the message. |
| 51 | +1. Clients send [`SendProxyMessage`][crate::external::bones_matchmaker_proto::SendProxyMessage]s to the server, specifying a target client (or all clients) and the message data. |
| 52 | +2. The server forwards these as [`RecvProxyMessage`][crate::external::bones_matchmaker_proto::RecvProxyMessage]s to the target client(s), including the sender's player index. |
92 | 53 |
|
93 | | -The matchmaking server supports forwarding both reliable and unreliable message in this way, |
94 | | -allowing the game to chose any kind of protocol it sees fit to synchronize the match data. |
| 54 | +The matchmaker supports both reliable and unreliable message forwarding, allowing the game to implement its preferred synchronization protocol. |
0 commit comments