|
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