Skip to content

Commit aa7520a

Browse files
committed
Finished Joining
1 parent f714beb commit aa7520a

File tree

1 file changed

+115
-11
lines changed

1 file changed

+115
-11
lines changed

Docfx/articles/features/joining.md

Lines changed: 115 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,43 @@
22
## Parties
33
Discord can show you and your friends in a party together for a specific game.
44

5-
todo: (xref:DiscordRPC.Party)
6-
todo: image of 2 people in a party
7-
todo: example code for parties
5+
![image of parties](https://i.lu.je/2025/firefox_cxOtJ1xrdJ.png)
6+
7+
The (xref:DiscordRPC.Party) can be used to create parties and control their size. With helper functions such as (xref:DiscordRPC.DiscordRpcClient.UpdatePartySize(int)) you can dynamically update when players join and leave.
8+
```cs
9+
client.SetPresence(new()
10+
{
11+
Details = "Party Example",
12+
State = "In Game",
13+
Party = new()
14+
{
15+
ID = "my-unique-party-id",
16+
Privacy = Party.PrivacySetting.Private,
17+
Size = 1,
18+
Max = 4,
19+
},
20+
});
21+
```
22+
The (xref:DiscordRPC.Party.ID) is a unique id (to your application) that tells Discord what party the user is currently in. When two users use the same ID, Discord will group them together.
23+
24+
> [!TIP]
25+
> If the size is set larger than actual number of users sharing the ID, then a default "fake" user is displayed instead.
26+
>
27+
> This value is also synchronised across all clients with the same ID.
828
929
## Joining / Lobbies
10-
You can provide a way for users to invite others to play your game either directly or by having a "Join Game" / "Request to Join" button on your presence.
30+
Users can use your Rich Presence as a very basic invite / join system. As long as the Party is set, you are able to provide special secret that discord will share to other users.
1131

1232
When accepted/joined, the other player's game will be launched and a (xref:DiscordRPC.DiscordRpcClient.OnJoin) will be called with the secret you provided in your presence.
1333

14-
todo: image here of a invite
34+
![image of join button](https://i.lu.je/2025/Discord_dT7xxZDifj.png)
1535

1636
> [!NOTE]
1737
> Rich Presence only sends your secret to the other player. Your game must be able to connect and manage lobbies itself.
1838
>
1939
> Check out [Steams Documentation](https://partner.steamgames.com/doc/features/multiplayer/matchmaking) for their lobbies.
2040
21-
### 1. Launching your game
41+
### Launching your game
2242
Discord uses custom [URI Schemes](https://developer.mozilla.org/en-US/docs/Web/URI/Reference/Schemes) to launch your game. It requires one to be set to show any of joining buttons.
2343

2444
This library provides functionality to do this. Before initializing, use the RegisterScheme function:
@@ -33,15 +53,99 @@ client.RegisterUriScheme("657300");
3353
client.Initialize();
3454
```
3555

56+
> [!NOTE]
57+
> You need to register the URI scheme to see other user's Join button and invites.
58+
3659
> [!WARNING]
3760
> MacOS requires schemes to be registered through [App Bundles](https://developer.apple.com/documentation/xcode/defining-a-custom-url-scheme-for-your-app). This library cannot access your App Bundle and cannot automatically register **non-steam** games.
3861
>
3962
> If you are publishing a MacOS game, you **must** provide either a `Steam App ID` or a custom uri scheme (such as `my-game://launch`) to the `RegisterUriScheme`.
4063
41-
### 2. Setting a Secret
64+
### Setting a Secret
65+
Users will connect to multiplayer sessions of your game using a shared secret. When a presence is set, you can designate a secret that will be shared with users who will use that to join.
66+
67+
This library doesn't provide a mechanism to connect to multiplayer sessions (match making) and will be dependant on your game, engine, and networking stack.
68+
69+
These secrets should contain enough data to know who & how to connect to someone but shouldn't include sensitive data like IP addresses.
70+
71+
As a basic example, consider this implementation:
72+
```cs
73+
client.SetPresence(new()
74+
{
75+
Details = "Party Example",
76+
State = "In Game",
77+
Party = new() { /* .. Party Details .. */ },
78+
79+
// This is how a launching app will figure out how to connect to the game.
80+
Secrets = new()
81+
{
82+
Join = Lobby.CreateJoinToken(Lobby.current.ID)
83+
},
84+
});
85+
86+
```
87+
88+
Note that `Lobby.current.ID` and `Lobby.CreateJoinToken()` will be up to your implementation. A naive approach would be a set password as the secret, but a better approach would be to use a signed key such as a [JWT](https://www.jwt.io/introduction#when-to-use-json-web-tokens) which contains a lobby ID and signed by the lobby host.
4289

43-
### 3. Accepting Requests
44-
todo (xref:DiscordRPC.DiscordRpcClient.OnJoinRequest)
90+
### Joining
91+
When a Party and Secret are set and the **viewing** user has had the URI Scheme registered, Discord will display a "Join" button on the presence.
4592

46-
### 4. Joining
47-
todo (xref:DiscordRPC.DiscordRpcClient.OnJoin)
93+
![join](https://i.lu.je/2025/Discord_dT7xxZDifj.png)
94+
95+
When a user clicks the Join button, Discord will launch the application using the URI Scheme that you registered earlier.
96+
97+
Your application will then need to subscribe to (). Once subscribed, Discord will then send a Join message via the (xref:DiscordRPC.DiscordRpcClient.OnJoin) event. Once this event is received, use the secret from the event to join the lobby.
98+
99+
Below is an example on this process:
100+
```cs
101+
client.Subscribe(EventType.Join);
102+
client.OnJoin += (object sender, JoinMessage args) => {
103+
Lobby.JoinWithToken(args.Secret);
104+
};
105+
```
106+
107+
> [!WARNING]
108+
> We do not automatically subscribe to events. This library is primarily uesd for simple Rich Presence and the Joining is a feature generally only useful for Games.
109+
>
110+
> Because of this, by default this app will not receive Discord Join events. You must call the (xref:DiscordRPC.DiscordRpcClient.subscribe).
111+
112+
> [!TIP]
113+
> You can directly invite users to play your game. They will see a game invitation like so, and if they have run the URI Scheme registration too, they will be able to launch from here.
114+
>
115+
> ![invite button](https://i.lu.je/2025/Discord_ivzV8uc0F8.png)
116+
117+
### Ask to Join
118+
To make your lobby a invite-only, set your (xref:DiscordRPC.Party.PrivacySetting) to `Private`.
119+
120+
This will change the "Join" button to a "Ask To Join". Users can directly respond to this in Discord, or you can listen to this event and respond to it directly in game using the (xref:DiscordRPC.DiscordRpcClient.OnJoinRequested)
121+
122+
![ask to join](https://i.lu.je/2025/Discord_P1f65SgZun.png)
123+
124+
Subscribe to these events and use the (xref:DiscordRPC.DiscordRpcClient.Respond):
125+
126+
```cs
127+
client.Subscribe(EventType.JoinRequest);
128+
client.OnJoinRequested += async (object sender, JoinRequestMessage args) => {
129+
var result = await UI.ShowRequestToJoin(args.user); // Hypothetical UI system
130+
client.Respond(args.User, result.accepted);
131+
};
132+
```
133+
134+
## Spectating
135+
Spectating has been removed from Discord.
136+
137+
## Code Example
138+
The [DiscordRPC.Example](https://github.com/Lachee/discord-rpc-csharp/blob/master/DiscordRPC.Example/Joining.cs) project contains a very basic example of the joining flow. Use 2 seperate clients as an example.
139+
140+
```sh
141+
# Run on the first pipe
142+
dotnet run --framework net9 --project DiscordRPC.Example --example=Joining --pipe=0
143+
144+
# Run on the second pipe
145+
dotnet run --framework net9 --project DiscordRPC.Example --example=Joining --pipe=1
146+
```
147+
148+
> [!NOTE]
149+
> While it does register a scheme, this example cannot launch properly because it just registers the dotnet runner.
150+
>
151+
> This wont be a problem in a full application.

0 commit comments

Comments
 (0)