diff --git a/docs/Change_Log.md b/docs/Change_Log.md
index 785455dcb8..6766af35dd 100644
--- a/docs/Change_Log.md
+++ b/docs/Change_Log.md
@@ -7,7 +7,7 @@
The [`SET_ACTIVITY` RPC command](#DOCS_TOPICS_RPC/setactivity) has been updated to support 3 additional [activity types](#DOCS_TOPICS_GATEWAY_EVENTS/activity-object-activity-types): Listening (`2`), Watching (`3`), and Competing (`5`). Previously, it only accepted Playing (`0`).
> warn
-> The [Game SDK](#DOCS_GAME_SDK_ACTIVITIES) has not been updated to support setting [`ActivityType`](#DOCS_GAME_SDK_ACTIVITIES/data-models-activitytype-enum), and is still limited to read-only (to handle events that you receive from Discord).
+> The [Game SDK](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activities) has not been updated to support setting [`ActivityType`](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activitytype-enum), and is still limited to read-only (to handle events that you receive from Discord).
## Application Emoji
@@ -683,14 +683,14 @@ In **late January or early February**, all servers will be migrated to the new b
To help keep us focused on the features, improvements, and gaming-related experiences that Discord users love, we are deprecating the following pieces of the GameSDK **starting today**, and decommissioning them on **Tuesday, May 2, 2023**:
-- [Achievements](#DOCS_GAME_SDK_ACHIEVEMENTS/)
-- [Applications](#DOCS_GAME_SDK_APPLICATIONS/)
-- [Voice](#DOCS_GAME_SDK_DISCORD_VOICE/)
-- [Images](#DOCS_GAME_SDK_IMAGES/)
-- [Lobbies](#DOCS_GAME_SDK_LOBBIES/)
-- [Networking](#DOCS_GAME_SDK_NETWORKING/)
-- [Storage](#DOCS_GAME_SDK_STORAGE/)
-- [Store](#DOCS_GAME_SDK_STORE/) [purchases and discounts]
+- [Achievements](#DOCS_DEVELOPER_TOOLS_GAME_SDK/achievements)
+- [Applications](#DOCS_DEVELOPER_TOOLS_GAME_SDK/applications)
+- [Voice](#DOCS_DEVELOPER_TOOLS_GAME_SDK/voice)
+- [Images](#DOCS_DEVELOPER_TOOLS_GAME_SDK/images)
+- [Lobbies](#DOCS_DEVELOPER_TOOLS_GAME_SDK/lobbies)
+- [Networking](#DOCS_DEVELOPER_TOOLS_GAME_SDK/networking)
+- [Storage](#DOCS_DEVELOPER_TOOLS_GAME_SDK/storage)
+- [Store](#DOCS_DEVELOPER_TOOLS_GAME_SDK/store) [purchases and discounts]
This deprecation period will last until **Tuesday May 2, 2023**, after which these pieces will be decommissioned and no longer work. The other pieces of the GameSDK will continue to be supported.
@@ -951,7 +951,7 @@ The `GET /guilds/{guild.id}/bans` endpoint has been migrated to require paginati
- To specify a reason for an administrative action in audit logs, apps must now pass the `X-Audit-Log-Reason` header rather than the `reason` parameter for all endpoints. Read more in the [Audit Logs documentation](#DOCS_RESOURCES_AUDIT_LOG).
- Message routes (like [`POST /channels/{channel.id}/messages`](#DOCS_RESOURCES_MESSAGE/create-message)) now use the `embeds` field (an array of embed objects) instead of `embed`.
- The `summary` field for [applications](#DOCS_RESOURCES_APPLICATION) now returns an empty string for all API versions.
-- The `name` and `description` fields for [Achievements](#DOCS_GAME_SDK_ACHIEVEMENTS/data-models-achievement-struct) are now strings, and localization info is now passed in new `name_localizations` and `description_localizations` dictionaries. This change standardizes localization to match [Application Commands](#DOCS_INTERACTIONS_APPLICATION_COMMANDS/localization). Read details in the [Achievements documentation](#DOCS_GAME_SDK_ACHIEVEMENTS/data-models-achievement-struct).
+- The `name` and `description` fields for [Achievements](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Achievements.md#achievement-struct) are now strings, and localization info is now passed in new `name_localizations` and `description_localizations` dictionaries. This change standardizes localization to match [Application Commands](#DOCS_INTERACTIONS_APPLICATION_COMMANDS/localization). Read details in the [Achievements documentation](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Achievements.md#achievement-struct).
- Existing attachments must be specified when [`PATCH`ing messages with new attachments](#DOCS_REFERENCE/editing-message-attachments). Any attachments not specified will be removed and replaced with the specified list
- Requests to v10 and higher will no longer be supported on `discordapp.com` (this does **not** affect `cdn.discordapp.com`)
@@ -1233,7 +1233,7 @@ We've added a new endpoint for deleting all reactions of a specific emoji from a
#### February 26, 2020
-The [Spectate](#DOCS_GAME_SDK_ACTIVITIES/onactivityspectate) functionality of Rich Presence no longer requires whitelisting or approval.
+The [Spectate](#DOCS_DEVELOPER_TOOLS_GAME_SDK/onactivityspectate) functionality of Rich Presence no longer requires whitelisting or approval.
## Gateway Intents
@@ -1267,9 +1267,9 @@ Fixed a bug from the 2.5.5 release that caused network handshakes to fail, resul
#### November 14, 2019
-We've shipped some updates to the GameSDK, including support for Linux as well as the IL2CPP backend system for Unity. These changes also fixed a bug in the [`SetUserAchievement()`](#DOCS_GAME_SDK_ACHIEVEMENTS/setuserachievement) method.
+We've shipped some updates to the GameSDK, including support for Linux as well as the IL2CPP backend system for Unity. These changes also fixed a bug in the [`SetUserAchievement()`](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Achievements.md#setuserachievement) method.
-Get the latest at the top of the [Getting Started](#DOCS_GAME_SDK_GETTING_STARTED/step-1-get-the-thing) documentation. If you're looking for help interacting with the GameSDK or want to report a bug, join us on the [official Discord](https://discord.gg/discord-developers).
+Get the latest at the top of the [Getting Started](#DOCS_DEVELOPER_TOOLS_GAME_SDK/step-1-get-the-sdk) documentation. If you're looking for help interacting with the GameSDK or want to report a bug, join us on the [official Discord](https://discord.gg/discord-developers).
## Changes to Special Channels
@@ -1287,7 +1287,7 @@ You can now get more precise rate limit reset times, via a new request header. C
#### July 18, 2019
-You can now use Bot tokens for authorization headers against the HTTP API for [Achievements](#DOCS_GAME_SDK_ACHIEVEMENTS/the-api-way).
+You can now use Bot tokens for authorization headers against the HTTP API for [Achievements](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Achievements.md#the-api-way).
## Additional Team Information
@@ -1305,7 +1305,7 @@ Additional information has been documented to support [Server Nitro Boosting](ht
#### April 29, 2019
-The [Discord-RPC](https://github.com/discord/discord-rpc) implementation of Rich Presence has been deprecated in favor of Discord's new GameSDK. If you're interested in using Rich Presence, please read our [SDK Starter Guide](#DOCS_GAME_SDK_GETTING_STARTED/) and check out the relevant functions in the [Activity Manager](#DOCS_GAME_SDK_ACTIVITIES/).
+The [Discord-RPC](https://github.com/discord/discord-rpc) implementation of Rich Presence has been deprecated in favor of Discord's new GameSDK. If you're interested in using Rich Presence, please read our [SDK Starter Guide](#DOCS_DEVELOPER_TOOLS_GAME_SDK/getting-started) and check out the relevant functions in the [Activity Manager](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activities).
## New Invite Object Fields
@@ -1379,7 +1379,7 @@ Rich Presence is now live and available for all developers! Rich Presence allows
- Allowing users to post invitations to join their party or spectate their game in chat
- Displaying "Spectate" and "Ask to Join" buttons on users' profiles
-For more information, check out our [Rich Presence site](https://discord.com/rich-presence). To get started on development, [read the docs](#DOCS_RICH_PRESENCE_HOW_TO/)!
+For more information, check out our [Rich Presence site](https://discord.com/rich-presence). To get started on development, [read the docs](#DOCS_RICH_PRESENCE_OVERVIEW)!
## Breaking Change: API & Gateway Below v6 Discontinued
diff --git a/docs/Intro.mdx b/docs/Intro.mdx
index 9f2bd7a056..f7e3077cd2 100644
--- a/docs/Intro.mdx
+++ b/docs/Intro.mdx
@@ -2,7 +2,7 @@
# Welcome to the Discord Developer Platform
-The Discord developer platform lets you develop apps to customize and extend Discord for millions of users. A toolkit of [APIs](#DOCS_REFERENCE) and [resources](#DOCS_TOPICS_COMMUNITY_RESOURCES) pair splendidly with a supportive community to help you build bots, integrate 3rd party services, and add Discord support to your game.
+The Discord developer platform lets you develop apps to customize and extend Discord for millions of users. A toolkit of [APIs](#DOCS_REFERENCE) and [resources](#DOCS_DEVELOPER_TOOLS_COMMUNITY_RESOURCES) pair splendidly with a supportive community to help you build bots, integrate 3rd party services, and add Discord support to your game.
@@ -22,7 +22,7 @@ Plus, use the [Gateway API](#DOCS_TOPICS_GATEWAY) to respond to [real-time event
#### Connect Metadata
-Link and update metadata to enhance Discord for users. Add [Rich Presence](#DOCS_GAME_SDK_ACTIVITIES) to display live data on users' profiles, or [connection metadata](#DOCS_RESOURCES_APPLICATION_ROLE_CONNECTION_METADATA) to make it easy for admins to create roles using metadata associated with your app.
+Link and update metadata to enhance Discord for users. Add [Rich Presence](#DOCS_RICH_PRESENCE_OVERVIEW) to display live data on users' profiles, or [connection metadata](#DOCS_RESOURCES_APPLICATION_ROLE_CONNECTION_METADATA) to make it easy for admins to create roles using metadata associated with your app.
#### Build Interactive Activities and Games
@@ -32,7 +32,7 @@ Currently in Developer Preview, the [Embedded App SDK](#DOCS_DEVELOPER_TOOLS_EMB
#### Find Tools and Libraries
-The Discord developer community has built and maintained a ton of different [libraries and tools](#DOCS_TOPICS_COMMUNITY_RESOURCES/libraries) over the years. No matter your experience level or language of choice, there are resources to speed up and simplify app development for you over on the [Community Resources](#DOCS_TOPICS_COMMUNITY_RESOURCES) page.
+The Discord developer community has built and maintained a ton of different [libraries and tools](#DOCS_DEVELOPER_TOOLS_COMMUNITY_RESOURCES/libraries) over the years. No matter your experience level or language of choice, there are resources to speed up and simplify app development for you over on the [Community Resources](#DOCS_DEVELOPER_TOOLS_COMMUNITY_RESOURCES) page.
You can also check out our [Postman collections](https://www.postman.com/discord-api) to try and test API endpoints.
diff --git a/docs/Reference.mdx b/docs/Reference.mdx
index 66384b02e5..0f0d82f05c 100644
--- a/docs/Reference.mdx
+++ b/docs/Reference.mdx
@@ -321,29 +321,29 @@ Discord uses ids and hashes to render images in the client. These hashes can be
###### CDN Endpoints
-| Type | Path | Supports |
-|-----------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------|
-| Custom Emoji | emojis/[emoji_id](#DOCS_RESOURCES_EMOJI/emoji-object).png | PNG, JPEG, WebP, GIF |
-| Guild Icon | icons/[guild_id](#DOCS_RESOURCES_GUILD/guild-object)/[guild_icon](#DOCS_RESOURCES_GUILD/guild-object).png \* | PNG, JPEG, WebP, GIF |
-| Guild Splash | splashes/[guild_id](#DOCS_RESOURCES_GUILD/guild-object)/[guild_splash](#DOCS_RESOURCES_GUILD/guild-object).png | PNG, JPEG, WebP |
-| Guild Discovery Splash | discovery-splashes/[guild_id](#DOCS_RESOURCES_GUILD/guild-object)/[guild_discovery_splash](#DOCS_RESOURCES_GUILD/guild-object).png | PNG, JPEG, WebP |
-| Guild Banner | banners/[guild_id](#DOCS_RESOURCES_GUILD/guild-object)/[guild_banner](#DOCS_RESOURCES_GUILD/guild-object).png \* | PNG, JPEG, WebP, GIF |
-| User Banner | banners/[user_id](#DOCS_RESOURCES_USER/user-object)/[user_banner](#DOCS_RESOURCES_USER/user-object).png \* | PNG, JPEG, WebP, GIF |
-| Default User Avatar | embed/avatars/[index](#DOCS_RESOURCES_USER/user-object).png \*\* \*\*\* | PNG |
-| User Avatar | avatars/[user_id](#DOCS_RESOURCES_USER/user-object)/[user_avatar](#DOCS_RESOURCES_USER/user-object).png \* | PNG, JPEG, WebP, GIF |
-| Guild Member Avatar | guilds/[guild_id](#DOCS_RESOURCES_GUILD/guild-object)/users/[user_id](#DOCS_RESOURCES_USER/user-object)/avatars/[member_avatar](#DOCS_RESOURCES_GUILD/guild-member-object).png \* | PNG, JPEG, WebP, GIF |
-| Avatar Decoration | avatar-decoration-presets/[avatar_decoration_data_asset](#DOCS_RESOURCES_USER/avatar-decoration-data-object).png | PNG |
-| Application Icon | app-icons/[application_id](#DOCS_RESOURCES_APPLICATION/application-object)/[icon](#DOCS_RESOURCES_APPLICATION/application-object).png | PNG, JPEG, WebP |
-| Application Cover | app-icons/[application_id](#DOCS_RESOURCES_APPLICATION/application-object)/[cover_image](#DOCS_RESOURCES_APPLICATION/application-object).png | PNG, JPEG, WebP |
-| Application Asset | app-assets/[application_id](#DOCS_RESOURCES_APPLICATION/application-object)/[asset_id](#DOCS_TOPICS_GATEWAY_EVENTS/activity-object-activity-assets).png | PNG, JPEG, WebP |
-| Achievement Icon | app-assets/[application_id](#DOCS_RESOURCES_APPLICATION/application-object)/achievements/[achievement_id](#DOCS_GAME_SDK_ACHIEVEMENTS/data-models-user-achievement-struct)/icons/[icon_hash](#DOCS_GAME_SDK_ACHIEVEMENTS/data-models-user-achievement-struct).png | PNG, JPEG, WebP |
-| Store Page Asset | app-assets/[application_id](#DOCS_RESOURCES_APPLICATION/application-object)/store/asset_id | PNG, JPEG, WebP |
-| Sticker Pack Banner | app-assets/710982414301790216/store/[sticker_pack_banner_asset_id](#DOCS_RESOURCES_STICKER/sticker-pack-object).png | PNG, JPEG, WebP |
-| Team Icon | team-icons/[team_id](#DOCS_TOPICS_TEAMS/data-models-team-object)/[team_icon](#DOCS_TOPICS_TEAMS/data-models-team-object).png | PNG, JPEG, WebP |
-| Sticker | stickers/[sticker_id](#DOCS_RESOURCES_STICKER/sticker-object).png \*\*\* \*\*\*\* | PNG, Lottie, GIF |
-| Role Icon | role-icons/[role_id](#DOCS_TOPICS_PERMISSIONS/role-object)/[role_icon](#DOCS_TOPICS_PERMISSIONS/role-object).png | PNG, JPEG, WebP |
-| Guild Scheduled Event Cover | guild-events/[scheduled_event_id](#DOCS_RESOURCES_GUILD_SCHEDULED_EVENT/guild-scheduled-event-object)/[scheduled_event_cover_image](#DOCS_RESOURCES_GUILD_SCHEDULED_EVENT/guild-scheduled-event-object).png | PNG, JPEG, WebP |
-| Guild Member Banner | guilds/[guild_id](#DOCS_RESOURCES_GUILD/guild-object)/users/[user_id](#DOCS_RESOURCES_USER/user-object)/banners/[member_banner](#DOCS_RESOURCES_GUILD/guild-member-object).png \* | PNG, JPEG, WebP, GIF |
+| Type | Path | Supports |
+|-----------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------|
+| Custom Emoji | emojis/[emoji_id](#DOCS_RESOURCES_EMOJI/emoji-object).png | PNG, JPEG, WebP, GIF |
+| Guild Icon | icons/[guild_id](#DOCS_RESOURCES_GUILD/guild-object)/[guild_icon](#DOCS_RESOURCES_GUILD/guild-object).png \* | PNG, JPEG, WebP, GIF |
+| Guild Splash | splashes/[guild_id](#DOCS_RESOURCES_GUILD/guild-object)/[guild_splash](#DOCS_RESOURCES_GUILD/guild-object).png | PNG, JPEG, WebP |
+| Guild Discovery Splash | discovery-splashes/[guild_id](#DOCS_RESOURCES_GUILD/guild-object)/[guild_discovery_splash](#DOCS_RESOURCES_GUILD/guild-object).png | PNG, JPEG, WebP |
+| Guild Banner | banners/[guild_id](#DOCS_RESOURCES_GUILD/guild-object)/[guild_banner](#DOCS_RESOURCES_GUILD/guild-object).png \* | PNG, JPEG, WebP, GIF |
+| User Banner | banners/[user_id](#DOCS_RESOURCES_USER/user-object)/[user_banner](#DOCS_RESOURCES_USER/user-object).png \* | PNG, JPEG, WebP, GIF |
+| Default User Avatar | embed/avatars/[index](#DOCS_RESOURCES_USER/user-object).png \*\* \*\*\* | PNG |
+| User Avatar | avatars/[user_id](#DOCS_RESOURCES_USER/user-object)/[user_avatar](#DOCS_RESOURCES_USER/user-object).png \* | PNG, JPEG, WebP, GIF |
+| Guild Member Avatar | guilds/[guild_id](#DOCS_RESOURCES_GUILD/guild-object)/users/[user_id](#DOCS_RESOURCES_USER/user-object)/avatars/[member_avatar](#DOCS_RESOURCES_GUILD/guild-member-object).png \* | PNG, JPEG, WebP, GIF |
+| Avatar Decoration | avatar-decoration-presets/[avatar_decoration_data_asset](#DOCS_RESOURCES_USER/avatar-decoration-data-object).png | PNG |
+| Application Icon | app-icons/[application_id](#DOCS_RESOURCES_APPLICATION/application-object)/[icon](#DOCS_RESOURCES_APPLICATION/application-object).png | PNG, JPEG, WebP |
+| Application Cover | app-icons/[application_id](#DOCS_RESOURCES_APPLICATION/application-object)/[cover_image](#DOCS_RESOURCES_APPLICATION/application-object).png | PNG, JPEG, WebP |
+| Application Asset | app-assets/[application_id](#DOCS_RESOURCES_APPLICATION/application-object)/[asset_id](#DOCS_TOPICS_GATEWAY_EVENTS/activity-object-activity-assets).png | PNG, JPEG, WebP |
+| Achievement Icon | app-assets/[application_id](#DOCS_RESOURCES_APPLICATION/application-object)/achievements/[achievement_id](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Achievements.md#user-achievement-struct)/icons/[icon_hash](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Achievements.md#user-achievement-struct).png | PNG, JPEG, WebP |
+| Store Page Asset | app-assets/[application_id](#DOCS_RESOURCES_APPLICATION/application-object)/store/asset_id | PNG, JPEG, WebP |
+| Sticker Pack Banner | app-assets/710982414301790216/store/[sticker_pack_banner_asset_id](#DOCS_RESOURCES_STICKER/sticker-pack-object).png | PNG, JPEG, WebP |
+| Team Icon | team-icons/[team_id](#DOCS_TOPICS_TEAMS/data-models-team-object)/[team_icon](#DOCS_TOPICS_TEAMS/data-models-team-object).png | PNG, JPEG, WebP |
+| Sticker | stickers/[sticker_id](#DOCS_RESOURCES_STICKER/sticker-object).png \*\*\* \*\*\*\* | PNG, Lottie, GIF |
+| Role Icon | role-icons/[role_id](#DOCS_TOPICS_PERMISSIONS/role-object)/[role_icon](#DOCS_TOPICS_PERMISSIONS/role-object).png | PNG, JPEG, WebP |
+| Guild Scheduled Event Cover | guild-events/[scheduled_event_id](#DOCS_RESOURCES_GUILD_SCHEDULED_EVENT/guild-scheduled-event-object)/[scheduled_event_cover_image](#DOCS_RESOURCES_GUILD_SCHEDULED_EVENT/guild-scheduled-event-object).png | PNG, JPEG, WebP |
+| Guild Member Banner | guilds/[guild_id](#DOCS_RESOURCES_GUILD/guild-object)/users/[user_id](#DOCS_RESOURCES_USER/user-object)/banners/[member_banner](#DOCS_RESOURCES_GUILD/guild-member-object).png \* | PNG, JPEG, WebP, GIF |
\* In the case of endpoints that support GIFs, the hash will begin with `a_` if it is available in GIF format. (example: `a_1269e74af4df7417b13759eae50c83dc`)
diff --git a/docs/topics/Community_Resources.md b/docs/developer_tools/Community_Resources.mdx
similarity index 100%
rename from docs/topics/Community_Resources.md
rename to docs/developer_tools/Community_Resources.mdx
index c03a533c1f..106423de25 100644
--- a/docs/topics/Community_Resources.md
+++ b/docs/developer_tools/Community_Resources.mdx
@@ -71,12 +71,6 @@ Discord does not maintain official SDKs. The following table is an inexhaustive
The public preview of the [Discord HTTP API specification](https://github.com/discord/discord-api-spec) provides a standard [OpenAPI 3.1 spec](https://github.com/OAI/OpenAPI-Specification/blob/main/versions/3.1.0.md) for the HTTP API.
-## Game SDK Tools
-
-Discord Game SDK's lobby and networking layer shares similarities with other gaming platforms (i.e. Valve's Steamworks SDK). The following open source library provides developers a uniform interface for these shared features and can simplify developing for multiple platforms. Note: this library is tailored for Unity3D development.
-
-- [HouraiNetworking](https://github.com/HouraiTeahouse/HouraiNetworking)
-
## Permission Calculators
[Permissions](#DOCS_TOPICS_PERMISSIONS/permissions) in Discord are tricky. Luckily, we've got really smart people who love us and have made some great permissions calculators. If you're making a bot for others, and you're not sure how to properly calculate permissions or generate your [authorization URL](#DOCS_TOPICS_OAUTH2/bot-authorization-flow), these are great tools:
@@ -105,3 +99,9 @@ If you're working on a project that interacts with our API, you might find an AP
|---------------------------------------------------------------------|------------|
| [dasgo](https://github.com/switchupcb/dasgo) | Go |
| [discord-api-types](https://github.com/discordjs/discord-api-types) | JavaScript |
+
+## Game SDK Tools
+
+Discord Game SDK's lobby and networking layer shares similarities with other gaming platforms (i.e. Valve's Steamworks SDK). The following open source library provides developers a uniform interface for these shared features and can simplify developing for multiple platforms. Note: this library is tailored for Unity3D development.
+
+- [HouraiNetworking](https://github.com/HouraiTeahouse/HouraiNetworking)
diff --git a/docs/developer_tools/Embedded_App_SDK.md b/docs/developer_tools/Embedded_App_SDK.mdx
similarity index 98%
rename from docs/developer_tools/Embedded_App_SDK.md
rename to docs/developer_tools/Embedded_App_SDK.mdx
index 2ae05a312e..ffa8c66523 100644
--- a/docs/developer_tools/Embedded_App_SDK.md
+++ b/docs/developer_tools/Embedded_App_SDK.mdx
@@ -479,9 +479,12 @@ await discordSdk.commands.openShareMomentDialog({
### setActivity()
-Modifies how your activity's rich presence is displayed in the Discord client.
+Modifies how your Activity's Rich Presence data is displayed in the Discord client. The inner `activity` field is a partial [Activity object](#DOCS_TOPICS_GATEWAY_EVENTS/activity-object-activity-structure).
+
+Read the guide on [Using Rich Presence with the Embedded App SDK](#DOCS_RICH_PRESENCE_USING_WITH_THE_EMBEDDED_APP_SDK) for more usage details.
#### Supported Platforms
+
| Web | iOS | Android |
|-----|-----|---------|
| ✅ | ✅ | ✅ |
diff --git a/docs/developer_tools/Game_SDK.mdx b/docs/developer_tools/Game_SDK.mdx
new file mode 100644
index 0000000000..7a81b46348
--- /dev/null
+++ b/docs/developer_tools/Game_SDK.mdx
@@ -0,0 +1,2428 @@
+# Game SDK
+
+Welcome to the documentation for the Discord Game SDK! We're glad you made it. The Game SDK helps you develop your 3rd party game or app, and integrate it with Discord.
+
+> danger
+> Many Game SDK features—including Achievements, Applications, Voice, Images, Lobbies, Networking, Storage, Store (purchases and discounts), and selling SKUs— have been deprecated. This page contains managers that aren't deprecated, but **they are not being actively developed**.
+
+---
+
+## Getting Started
+
+This section will walk you through the first few steps you need to take to get up-and-running with the Game SDK. After you download the SDK and configure your app, you can find more details in the [Using the SDK section](#DOCS_DEVELOPER_TOOLS_GAME_SDK/using-the-sdk).
+
+### Step 1: Get the SDK
+
+Now, let's get started. First, get the SDK. Here it is:
+
+- [Discord Game SDK v3.2.1](https://dl-game-sdk.discordapp.net/3.2.1/discord_game_sdk.zip) - Latest version, includes Apple silicon (aarch64) support
+- [Discord Game SDK v2.5.6](https://dl-game-sdk.discordapp.net/2.5.6/discord_game_sdk.zip) - Try this version if you encounter bugs on the latest version
+
+There's a few things in there, but let's quickly talk about what the SDK actually _is_. Inside the `lib/` folder, you'll see `x86/` and `x86_64/` that have some `.lib`, `.bundle`, and `.dll` files. These are the things you want to distribute with your game.
+
+These files are comprised of two parts: a "stub", and fallback modules. What that means is that when everything is running smoothly, the DLLs will just call back to the local running Discord client to do the heavy lifting. If, however, something is wrong, like a breaking change, the files also include "fallback" modules that reflect the native SDK modules in Discord at the time that version of the SDK was published. TLDR - you don't need to worry about breaking changes.
+
+### Step 2: Create your App
+
+Next, we need to set up the application for your game. An [app](#DOCS_RESOURCES_APPLICATION) is the base "entity" in Discord for your game; it's what all the builds, branches, SKUs, store pages, assets, etc. will be filed under.
+
+Head over to our [developer site](https://discord.com/developers/) and create an account/log in if you haven't yet. The first thing we're going to do is create a Team. Teams are groups of developers working together on applications; you should create a team for your organization at [https://discord.com/developers/teams](https://discord.com/developers/teams). You can invite other users to join your team and work on applications together with you.
+
+Now that your team is created, you'll want to make an application. To do so, click on "Applications" at the top of the page and create an application. Make sure you pick your newly-created team in the `Team` dropdown. You want your team to own the application; this unlocks store functionality! Now that your app is made, let's dive into some more setup.
+
+> warn
+> If you're integrating our SDK into an already-released game, there's a good chance that we may _already have_ an application in our database for your game! Reach out to our [Dev Support](https://dis.gd/devsupport) to learn more
+
+First, we'll need to set an OAuth2 redirect URL. You can add `http://127.0.0.1` in there for now; this powers some behind-the-scenes stuff you don't need to worry about.
+
+Next, copy the **Client ID** at the top of the page. This id, also referred to as an "application id", is your game's unique identifier across Discord. Keep it handy!
+
+While you're here, head to the "OAuth2" section of your application and add `http://127.0.0.1` as a redirect URI for your application. This will allow us to do the OAuth2 token exchange within the Discord client.
+
+### Step 3: Start Coding
+
+Before you start developing, there are a couple of notes to keep in mind about the SDK:
+
+- All strings in the SDK are UTF8 strings. Make sure you've converted properly if necessary!
+- The SDK is **_NOT_** threadsafe!
+
+With that out of the way, let's start coding. Didn't think we'd get there so fast, did ya? _Think again!_ The dropdowns are code primers for the main languages of the SDK: C#, C, and C++. They'll get you up and running with the most basic examples, and then you're off to the races.
+
+
+- Open up that SDK zip that you downloaded.
+- Copy the contents of the `lib/` folder to `Assets/Plugins` in your Unity project
+- Copy the contents of the `csharp/` folder to `Assets/Plugins/DiscordGame SDK`
+
+From there, you'll be able to reference functions in the DLL within your scripts. A basic example of a script can be found [in this example repo](https://github.com/msciotti/discord-game-sdk-test-apps/tree/master/cs-examples/unity-examples/Assets). In this example, we attach our `DiscordController.cs` script to the Main Camera object of the default created scene. We then instantiate the SDK with:
+
+```cs
+/*
+ Grab that Client ID from earlier
+ Discord.CreateFlags.Default will require Discord to be running for the game to work
+ If Discord is not running, it will:
+ 1. Close your game
+ 2. Open Discord
+ 3. Attempt to re-open your game
+ Step 3 will fail when running directly from the Unity editor
+ Therefore, always keep Discord running during tests, or use Discord.CreateFlags.NoRequireDiscord
+*/
+var discord = new Discord.Discord(CLIENT_ID, (UInt64)Discord.CreateFlags.Default);
+```
+
+You're now free to use other functionality in the SDK! Make sure to call `discord.RunCallbacks()` in your main game loop; that's your `Update()` function.
+
+You're ready to go! Check out the rest of the documentation for more info on how to use the other pieces of the SDK. See an example of everything it can do in `examples/Program.cs` in the SDK zip file.
+
+
+
+- Open up that SDK zip that you downloaded.
+- Create a folder in your project directory called `DiscordGame SDK` and copy the contents of the `csharp/` folder to it
+- Build your solution then place the `.dll` in the directory of the `.exe` (either x86 or x86_64 version depending on your compile platform). If you compile for Any CPU you may need to perform additional wrapping around DLL importing (like setting the DLL directory dynamically) to make sure you load the correct DLL.
+
+From there, you'll be able to reference functions in the DLL within your scripts. We then instantiate the SDK with:
+
+```cs
+/*
+ Grab that Client ID from earlier
+ Discord.CreateFlags.Default will require Discord to be running for the game to work
+ If Discord is not running, it will:
+ 1. Close your game
+ 2. Open Discord
+ 3. Attempt to re-open your game
+ Step 3 may fail when running directly from your editor
+ Therefore, always keep Discord running during tests, or use Discord.CreateFlags.NoRequireDiscord
+*/
+var discord = new Discord.Discord(CLIENT_ID, (UInt64)Discord.CreateFlags.Default);
+```
+
+You're now free to use other functionality in the SDK! Make sure to call `discord.RunCallbacks()` in your main game loop; that's your `Update()` function.
+
+You're ready to go! Check out the rest of the documentation for more info on how to use the other pieces of the SDK. See an example of everything it can do in `examples/Program.cs` in the SDK zip file.
+
+
+
+Before jumping into the C binding, a word of caution. If you are using Unreal Engine 3, or need to support an older version of Visual Studio, you may at first see some unexpected crashes due to compile configurations. The way to fix this is to wrap the include statement for the Discord Game SDK header file like so:
+
+```c
+#pragma pack(push, 8)
+#include "discord_game_sdk.h"
+#pragma pack(pop)
+```
+
+This should let you use the SDK without any further crashes. Now, on with the show!
+
+- Open up that SDK zip that you downloaded.
+- Copy the contents of the `lib/` folder to the best location within your project for DLLs.
+- Copy the contents of the `c/` folder to your source directory
+- It's dangerous to go alone—take this small code block with you (to start)!
+
+```c
+struct Application {
+ struct IDiscordCore* core;
+ struct IDiscordUsers* users;
+};
+
+struct Application app;
+// Don't forget to memset or otherwise initialize your classes!
+memset(&app, 0, sizeof(app));
+
+struct IDiscordCoreEvents events;
+memset(&events, 0, sizeof(events));
+
+struct DiscordCreateParams params;
+params.client_id = CLIENT_ID;
+params.flags = DiscordCreateFlags_Default;
+params.events = &events;
+params.event_data = &app;
+
+DiscordCreate(DISCORD_VERSION, ¶ms, &app.core);
+```
+
+- Make sure to call `core->run_callbacks(core, 0)` in your game loop.
+
+You're ready to go! Check out the rest of the documentation for more info on how to use the other pieces of the SDK. See an example of everything it can do in `examples/c/main.c` in the SDK zip file.
+
+
+
+First, you'll want to copy the header files and `.cpp` files to a folder somewhere in your project directory. For ease of a quickstart example, you can put them right inside your `Source/your-project-name` folder; I'd put them in a containing folder called something like `discord-files/`.
+
+Second, you'll want to copy the `.dll` and `.lib` files from the `lib/x86_64` folder of the downloaded zip. These files should be put in `your-project-name/Binaries/Win64/`. For win32, take the files from `x86/` and put them, in `your-project-name/Binaries/Win32`.
+
+Next, we need to link these files within our project so that we can reference them. If you open up your project's `.sln` file in Visual Studio, you'll find a file called `your-project-name.Build.cs`. We're going to add the following lines of code to that file:
+
+```cpp
+/*
+ ABSOLUTE_PATH_TO_DISCORD_FILES_DIRECTORY will look something like:
+
+ "H:\\Unreal Projects\\Game SDKtest\\Source\\Game SDKtest\\discord-files\\"
+
+ You should get this value programmatically
+*/
+PublicIncludePaths.Add(ABSOLUTE_PATH_TO_DISCORD_FILES_DIRECTORY)
+
+/*
+ ABSOLUTE_PATH_TO_LIB_FILE will look something like:
+
+ "H:\\Unreal Projects\\Game SDKtest\\Binaries\\Win64\\discord_game_sdk.dll.lib"
+
+ You should get this value programmatically
+*/
+PublicAdditionalLibraries.Add(ABSOLUTE_PATH_TO_LIB_FILE)
+```
+
+Now that we've got our new dependencies properly linked, we can reference them in our code. In this example, we're going to make a new `Pawn` class called `MyPawn`. It will look something like this:
+
+```cpp
+#include "MyPawn.h"
+#include "discord-files/discord.h"
+
+discord::Core* core{};
+
+AMyPawn::AMyPawn()
+{
+ // Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
+ PrimaryActorTick.bCanEverTick = true;
+}
+
+// Called when the game starts or when spawned
+void AMyPawn::BeginPlay()
+{
+ Super::BeginPlay();
+ /*
+ Grab that Client ID from earlier
+ Discord.CreateFlags.Default will require Discord to be running for the game to work
+ If Discord is not running, it will:
+ 1. Close your game
+ 2. Open Discord
+ 3. Attempt to re-open your game
+ Step 3 will fail when running directly from the Unreal Engine editor
+ Therefore, always keep Discord running during tests, or use Discord.CreateFlags.NoRequireDiscord
+ */
+ auto result = discord::Core::Create(461618159171141643, DiscordCreateFlags_Default, &core);
+ discord::Activity activity{};
+ activity.SetState("Testing");
+ activity.SetDetails("Fruit Loops");
+ core->ActivityManager().UpdateActivity(activity, [](discord::Result result) {
+
+ });
+}
+
+// Called every frame
+void AMyPawn::Tick(float DeltaTime)
+{
+ Super::Tick(DeltaTime);
+ ::core->RunCallbacks();
+}
+
+// Called to bind functionality to input
+void AMyPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
+{
+ Super::SetupPlayerInputComponent(PlayerInputComponent);
+}
+```
+
+Make sure you've got `core->RunCallbacks()` going every frame!
+
+You're ready to go! Check out the rest of the documentation for more info on how to use the other pieces of the SDK. See an example of everything it can do in `examples/cpp/main.cpp` in the SDK zip file.
+
+
+
+In your project folder, you'll want to make something like a "discord-files" folder, for organization. In that folder, copy all the `.h` and `.cpp` files from the zip.
+You want to include all the header and source files respectively in your project
+
+
+
+In your project settings, you'll want to include the relevant library (e.g. `discord_game_sdk.dll.lib`) as an additional dependency.
+
+
+
+- From there, you should be able to `#include "discord-files/discord.h"`, or whatever the path to that header file is, and have access to the code.
+
+
+## Using the SDK
+
+At a high level, the Discord Game SDK has a parent class, `Discord`.
+
+This class is in charge of the creation of a few "manager" sub-classes to interact with Discord.
+
+### Managers
+
+Each manager class contains its own functions and events used to interact with Discord in the context of the manager:
+
+| Name | Description |
+|-----------------------------------------------------------------------|---------------------------------------------------------------------------------------------|
+| [`ActivityManager`](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activities) | for Rich Presence and game invites |
+| [`OverlayManager`](#DOCS_DEVELOPER_TOOLS_GAME_SDK/overlay) | for interacting with Discord's built-in overlay |
+| [`RelationshipManager`](#DOCS_DEVELOPER_TOOLS_GAME_SDK/relationships) | for users' social relationships across Discord, including friends list |
+| [`StoreManager`](#DOCS_DEVELOPER_TOOLS_GAME_SDK/store) | for all things entitlements and SKUs; purchases, discounts, and selling SKUs are deprecated |
+| [`UserManager`](#DOCS_DEVELOPER_TOOLS_GAME_SDK/users) | for fetching user data for a given id and the current user |
+
+Many managers in the Game SDK have been deprecated. You can see the deprecated managers in the dropdown below, and find the old documentation for each deprecated manager in the [deprecated section](#DOCS_DEVELOPER_TOOLS_GAME_SDK/deprecated) below.
+
+
+
+| Name | Description |
+|----------------------|------------------------------------------------------------------------------|
+| `AchievementManager` | for achievements! |
+| `ApplicationManager` | for retrieving a user's OAuth2 bearer token, locale, and current game branch |
+| `ImageManager` | for getting data about images on Discord, like user avatars or chat images |
+| `LobbyManager` | for multiplayer lobbies |
+| `NetworkManager` | for all your networking layer needs |
+| `StorageManager` | for saving game data to the disk and the cloud |
+| `VoiceManager` | to make use of Discord's awesome voice chat |
+
+
+
+### Using Functions in the SDK
+
+Most functions in the Discord Game SDK, uh, _function_ in a similar way. They take whatever parameters are required for the function to do its job—a user id, the requested size for an image, etc.—and a callback by means of a function pointer. That callback is fired when the function completes its work, letting you handle events without worrying about piping asynchronously-returned data to the right context.
+
+Some functions behave with a normal return behavior; e.g. `RelationshipManager.Count()` just returns the number directly. Don't worry, it's outlined in the docs.
+
+
+
+```c#
+var userManager = discord.GetUserManager();
+
+// Return via callback
+userManager.GetUser(290926444748734465, (Discord.Result result, ref Discord.User otherUser) =>
+{
+ if (result == Discord.Result.Ok)
+ {
+ Console.WriteLine(otherUser.Username);
+ Console.WriteLine(otherUser.Id);
+ }
+});
+
+
+// Return normally
+userManager.OnCurrentUserUpdate += () =>
+{
+ var currentUser = userManager.GetCurrentUser();
+ Console.WriteLine(currentUser.Username);
+ Console.WriteLine(currentUser.Discriminator);
+ Console.WriteLine(currentUser.Id);
+};
+```
+
+
+
+### Environment Variables
+
+Discord passes a number of environment variables down to the SDK. These are accessed by various functions in the SDK and can be changed for local testing by changing the value in your local environment.
+
+| name | method | description |
+|------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|
+| DISCORD_INSTANCE_ID | [Local Testing](#DOCS_DEVELOPER_TOOLS_GAME_SDK/testing-locally) | the locally running instance of Discord to connect to; allows you to choose between multiple running clients |
+| DISCORD_ACCESS_TOKEN | [ApplicationManager.GetOAuth2Token()](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Applications.md#getoauth2token) | the connected user's bearer token |
+| DISCORD_CURRENT_LOCALE | [ApplicationManager.GetCurrentLocale()](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Applications.md#getcurrentlocale) | the language that Discord is in for the connected user |
+| DISCORD_CURRENT_BRANCH | [ApplicationManager.GetCurrentBranch()](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Applications.md#getcurrentbranch) | the branch of the running application that the user has launched |
+| DISCORD_STORAGE_PATH | [StorageManager.GetPath()](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Storage.md#getpath) | the path to which Discord will save files if you're using the StorageManager |
+
+### Error Handling
+
+Debugging is a pain, so before we get into the meat of the SDK, we want to make sure you're prepared for when things go awry. Within the Discord core is a function called `SetLogHook()`. It takes a `level`, which is minimum level of log message you want to listen to, and a callback function:
+
+
+
+```cs
+public void LogProblemsFunction(Discord.LogLevel level, string message)
+{
+ Console.WriteLine("Discord:{0} - {1}", level, message);
+}
+
+discord.SetLogHook(Discord.LogLevel.Debug, LogProblemsFunction);
+```
+
+You should begin your integration by setting up this callback to help you debug. Helpfully, if you put a breakpoint inside the callback function you register here, you'll be able to see the stack trace for errors you run into (as long as they fail synchronously). Take the guess work out of debugging, or hey, ignore any and all logging by setting a callback that does nothing. We're not here to judge.
+
+
+### Testing Locally
+
+While integrating the Discord Game SDK, you will probably find yourself wanting to test functionality between two game clients locally, be it for networking, Rich Presence, etc.
+
+We know that getting a test build of a game on two separate machines can be both difficult and cumbersome. So, we've got a solution for you!
+
+
+
+> info
+> Value from environment variable `DISCORD_INSTANCE_ID`
+
+By using system environment variables, you can tell the SDK in a certain game client to connect to a specific Discord client. Here's how it works:
+
+1. Download Discord Canary. This is our most updated build, and is good to develop against: [Windows](https://discord.com/api/download/canary?platform=win) - [Mac](https://discord.com/api/download/canary?platform=osx)
+2. Download a second Discord Build. Here's our Public Test Build: [Windows](https://discord.com/api/download/ptb?platform=win) - [Mac](https://discord.com/api/download/ptb?platform=osx)
+3. Open up two Discord clients. We recommend you develop against Discord Canary, so you can use PTB or Stable for your test account
+4. Log in with two separate users. Make sure any test account is added to the application's App Whitelist in the portal!
+
+Now, in your game code, you can tell the SDK which client to connect to via the environment variable `DISCORD_INSTANCE_ID` **before initializing the SDK**. The value of the variable corresponds to the order in which you opened the clients, so `0` would connect to the first opened client, `1` the second, etc.
+
+###### Environment Variable Example
+
+```cs
+// This machine opened Discord Canary first, and Discord PTB second
+
+// This makes the SDK connect to Canary
+System.Environment.SetEnvironmentVariable("DISCORD_INSTANCE_ID", "0");
+var discord = new Discord(applicationId, Discord.CreateFlags.Default);
+
+// This makes the SDK connect to PTB
+System.Environment.SetEnvironmentVariable("DISCORD_INSTANCE_ID", "1");
+var discord = new Discord(applicationId, Discord.CreateFlags.Default);
+```
+
+This will set the environment variable only within the context of the running process, so don't worry about messing up global stuff.
+
+> danger
+> If you test with this, make sure to remove this code before pushing a production build. It will interfere with the way that Discord launches games for users.
+
+
+
+### Data Models
+
+#### Result Enum
+
+
+
+
+| Code | value | description |
+|------|---------------------------------|-------------------------------------------------------------------------------------------------|
+| 0 | Ok | everything is good |
+| 1 | ServiceUnavailable | Discord isn't working |
+| 2 | InvalidVersion | the SDK version may be outdated |
+| 3 | LockFailed | an internal error on transactional operations |
+| 4 | InternalError | something on our side went wrong |
+| 5 | InvalidPayload | the data you sent didn't match what we expect |
+| 6 | InvalidCommand | that's not a thing you can do |
+| 7 | InvalidPermissions | you aren't authorized to do that |
+| 8 | NotFetched | couldn't fetch what you wanted |
+| 9 | NotFound | what you're looking for doesn't exist |
+| 10 | Conflict | user already has a network connection open on that channel |
+| 11 | InvalidSecret | activity secrets must be unique and not match party id |
+| 12 | InvalidJoinSecret | join request for that user does not exist |
+| 13 | NoEligibleActivity | you accidentally set an `ApplicationId` in your `UpdateActivity()` payload |
+| 14 | InvalidInvite | your game invite is no longer valid |
+| 15 | NotAuthenticated | the internal auth call failed for the user, and you can't do this |
+| 16 | InvalidAccessToken | the user's bearer token is invalid |
+| 17 | ApplicationMismatch | access token belongs to another application |
+| 18 | InvalidDataUrl | something internally went wrong fetching image data |
+| 19 | InvalidBase64 | not valid Base64 data |
+| 20 | NotFiltered | you're trying to access the list before creating a stable list with `Filter()` |
+| 21 | LobbyFull | the lobby is full |
+| 22 | InvalidLobbySecret | the secret you're using to connect is wrong |
+| 23 | InvalidFilename | file name is too long |
+| 24 | InvalidFileSize | file is too large |
+| 25 | InvalidEntitlement | the user does not have the right entitlement for this game |
+| 26 | NotInstalled | Discord is not installed |
+| 27 | NotRunning | Discord is not running |
+| 28 | InsufficientBuffer | insufficient buffer space when trying to write |
+| 29 | PurchaseCancelled | user cancelled the purchase flow |
+| 30 | InvalidGuild | Discord guild does not exist |
+| 31 | InvalidEvent | the event you're trying to subscribe to does not exist |
+| 32 | InvalidChannel | Discord channel does not exist |
+| 33 | InvalidOrigin | the origin header on the socket does not match what you've registered (you should not see this) |
+| 34 | RateLimited | you are calling that method too quickly |
+| 35 | OAuth2Error | the OAuth2 process failed at some point |
+| 36 | SelectChannelTimeout | the user took too long selecting a channel for an invite |
+| 37 | GetGuildTimeout | took too long trying to fetch the guild |
+| 38 | SelectVoiceForceRequired | push to talk is required for this channel |
+| 39 | CaptureShortcutAlreadyListening | that push to talk shortcut is already registered |
+| 40 | UnauthorizedForAchievement | your application cannot update this achievement |
+| 41 | InvalidGiftCode | the gift code is not valid |
+| 42 | PurchaseError | something went wrong during the purchase flow |
+| 43 | TransactionAborted | purchase flow aborted because the SDK is being torn down |
+
+
+
+#### LogLevel Enum
+
+
+
+| value | description |
+|---------|--------------------------------|
+| Error | Log only errors |
+| Warning | Log warnings and errors |
+| Info | Log info, warnings, and errors |
+| Debug | Log _all_ the things! |
+
+
+
+#### CreateFlags Enum
+
+
+
+| value | description |
+|------------------|---------------------------------------------------------------------|
+| Default | Requires Discord to be running to play the game |
+| NoRequireDiscord | Does not require Discord to be running, use this on other platforms |
+
+
+
+### Functions
+
+#### Create
+
+Creates an instance of Discord to initialize the SDK. This is the overlord of all things Discord. We like to call her Nelly.
+
+Returns a new `Discord`.
+
+###### Parameters
+
+| name | type | description |
+|----------|-------------|-----------------------------------------------------|
+| clientId | Int64 | your application's client id |
+| flags | CreateFlags | the creation parameters for the SDK, outlined above |
+
+###### Example
+
+```cpp
+// c++ land
+discord::Core* core{};
+discord::Core::Create(53908232506183680, DiscordCreateFlags_Default, &core);
+
+// c# land
+var discord = new Discord(53908232506183680, (UInt64)Discord.CreateFlags.Default);
+```
+
+#### Destroy
+
+Destroys the instance. Wave goodbye, Nelly! You monster. In C# land, this is `Dispose()`.
+
+> info
+> The C++ binding does not include a `destroy()` method, as the destructor for the Core does the work for you.
+
+Returns `void`.
+
+###### Example
+
+```cs
+discord.Dispose();
+```
+
+#### SetLogHook
+
+Registers a logging callback function with the minimum level of message to receive. The callback function should have a signature of:
+
+```cs
+MyCallbackFunction(LogLevel level, string message);
+```
+
+Returns `void`.
+
+###### Parameters
+
+| name | type | description |
+|----------|----------|---------------------------------------------|
+| level | LogLevel | the minimum level of event to log |
+| callback | function | the callback function to catch the messages |
+
+###### Example
+
+```cs
+public void LogProblemsFunction(Discord.LogLevel level, string message)
+{
+ Console.WriteLine("Discord:{0} - {1}", level, message);
+}
+
+discord.SetLogHook(Discord.LogLevel.Debug, LogProblemFunctions);
+```
+
+#### RunCallbacks
+
+Runs all pending SDK callbacks. Put this in your game's main event loop, like `Update()` in Unity. That way, the first thing your game does is check for any new info from Discord.
+
+This function also serves as a way to know that the local Discord client is still connected. If the user closes Discord while playing your game, `RunCallbacks()` will return/throw `Discord.Result.NotRunning`.
+
+In C and C++, this function returns `Discord.Result`. In C#, it returns `void` and will throw `Discord.Result` error if something went wrong.
+
+###### Example
+
+```cs
+void Update()
+{
+ discord.RunCallbacks();
+}
+```
+
+#### GetActivityManager
+
+Fetches an instance of the manager for interfacing with activities in the SDK.
+
+Returns an `ActivityManager`.
+
+###### Example
+
+```cs
+var activityManager = discord.GetActivityManager();
+```
+
+#### GetRelationshipManager
+
+Fetches an instance of the manager for interfacing with relationships in the SDK.
+
+Returns a `RelationshipManager`.
+
+###### Example
+
+```cs
+var relationshipManager = discord.GetRelationshipManager();
+```
+
+#### GetImageManager
+
+Fetches an instance of the manager for interfacing with images in the SDK.
+
+Returns an `ImageManager`.
+
+###### Example
+
+```cs
+var imageManager = discord.GetImageManager();
+```
+
+#### GetUserManager
+
+Fetches an instance of the manager for interfacing with users in the SDK.
+
+Returns an `UserManager`.
+
+###### Example
+
+```cs
+var userManager = discord.GetUserManager();
+```
+
+#### GetLobbyManager
+
+Fetches an instance of the manager for interfacing with lobbies in the SDK.
+
+Returns a `LobbyManager`.
+
+###### Example
+
+```cs
+var lobbyManager = discord.GetLobbyManager();
+```
+
+#### GetNetworkManager
+
+Fetches an instance of the manager for interfacing with networking in the SDK.
+
+Returns an `NetworkManager`.
+
+###### Example
+
+```cs
+var networkManager = discord.GetNetworkManager();
+```
+
+#### GetOverlayManager
+
+Fetches an instance of the manager for interfacing with the overlay in the SDK.
+
+Returns an `OverlayManager`.
+
+###### Example
+
+```cs
+var overlayManager = discord.GetOverlayManager();
+```
+
+#### GetApplicationManager
+
+Fetches an instance of the manager for interfacing with applications in the SDK.
+
+Returns an `ApplicationManager`.
+
+###### Example
+
+```cs
+var applicationManager = discord.GetApplicationManager();
+```
+
+#### GetStorageManager
+
+Fetches an instance of the manager for interfacing with storage in the SDK.
+
+Returns a `StorageManager`.
+
+###### Example
+
+```cs
+var storageManager = discord.GetStorageManager();
+```
+
+#### GetStoreManager
+
+Fetches an instance of the manager for interfacing with SKUs and Entitlements in the SDK.
+
+Returns a `StoreManager`.
+
+###### Example
+
+```cs
+var storeManager = discord.GetStoreManager();
+```
+
+#### GetVoiceManager
+
+Fetches an instance of the manager for interfacing with voice chat in the SDK.
+
+Returns a `VoiceManager`.
+
+###### Example
+
+```cs
+var voiceManager = discord.GetVoiceManager();
+```
+
+#### GetAchievementManager
+
+Fetches an instance of the manager for interfacing with achievements in the SDK.
+
+Returns an `AchievementManager`.
+
+###### Example
+
+```cs
+var achievementManager = discord.GetAchievementManager();
+```
+
+## Activities
+
+> info
+> Looking to build a game inside of Discord? Check out the (other) [Activities](#DOCS_ACTIVITIES_OVERVIEW) and the [Embedded SDK](#DOCS_DEVELOPER_TOOLS_EMBEDDED_APP_SDK) documentation.
+
+Looking to integrate Rich Presence into your game? No need to manage multiple SDKs—this one does all that awesome stuff, too! Delight your players with the ability to post game invites in chat and party up directly from Discord. Surface interesting live game data in their profile for their friends, encouraging them to group up and play together.
+
+For more detailed information and documentation around the Rich Presence feature set and integration tips, check out our [Rich Presence Documentation](#DOCS_RICH_PRESENCE_OVERVIEW).
+
+### Data Models
+
+#### User Struct
+
+| name | type | description |
+|---------------|--------|-------------------------------|
+| Id | Int64 | the user's id |
+| Username | string | their name |
+| Discriminator | string | the user's unique discrim |
+| Avatar | string | the hash of the user's avatar |
+| Bot | bool | if the user is a bot user |
+
+#### Activity Struct
+
+| name | type | description |
+|---------------|--------------------------------------------------------------------------------|-----------------------------------------------------------------|
+| ApplicationId | Int64 | your application id - this is a read-only field |
+| Name | string | name of the application - this is a read-only field |
+| State | string | the player's current party status |
+| Details | string | what the player is currently doing |
+| Timestamps | [ActivityTimestamps](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activitytimestamps-struct) | helps create elapsed/remaining timestamps on a player's profile |
+| Assets | [ActivityAssets](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activityassets-struct) | assets to display on the player's profile |
+| Party | [ActivityParty](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activityparty-struct) | information about the player's party |
+| Secrets | [ActivitySecrets](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activitysecrets-struct) | secret passwords for joining and spectating the player's game |
+| Instance | bool | whether this activity is an instanced context, like a match |
+
+#### ActivityTimestamps Struct
+
+| name | type | description |
+|-------|-------|--------------------------------------------------------|
+| Start | Int64 | unix timestamp - send this to have an "elapsed" timer |
+| End | Int64 | unix timestamp - send this to have a "remaining" timer |
+
+#### ActivityAssets Struct
+
+| name | type | description |
+|------------|--------|----------------------------------------------------------------------------------------------|
+| LargeImage | string | see [Activity Asset Image](#DOCS_TOPICS_GATEWAY_EVENTS/activity-object-activity-asset-image) |
+| LargeText | string | hover text for the large image |
+| SmallImage | string | see [Activity Asset Image](#DOCS_TOPICS_GATEWAY_EVENTS/activity-object-activity-asset-image) |
+| SmallText | string | hover text for the small image |
+
+#### ActivityParty Struct
+
+| name | type | description |
+|------|-----------|------------------------------------|
+| Id | string | a unique identifier for this party |
+| Size | PartySize | info about the size of the party |
+
+#### PartySize Struct
+
+| name | type | description |
+|-------------|-------|------------------------------------|
+| CurrentSize | Int32 | the current size of the party |
+| MaxSize | Int32 | the max possible size of the party |
+
+#### ActivitySecrets Struct
+
+| name | type | description |
+|----------|--------|----------------------------------------------|
+| Match | string | unique hash for the given match context |
+| Join | string | unique hash for chat invites and Ask to Join |
+| Spectate | string | unique hash for Spectate button |
+
+#### ActivityType Enum
+
+| name | Value |
+|-----------|-------|
+| Playing | 0 |
+| Streaming | 1 |
+| Listening | 2 |
+| Watching | 3 |
+| Custom | 4 |
+| Competing | 5 |
+
+For more details about the activity types, [see Gateway documentation](#DOCS_TOPICS_GATEWAY_EVENTS//activity-object-activity-types).
+
+`ActivityType` is strictly for the purpose of handling events that you receive from Discord; though the SDK will not reject a payload with an `ActivityType` sent, it will be discarded and will not change anything in the client.
+
+#### ActivityJoinRequestReply Enum
+
+| name | value |
+|--------|-------|
+| No | 0 |
+| Yes | 1 |
+| Ignore | 2 |
+
+#### ActivityActionType Enum
+
+| name | value |
+|----------|-------|
+| Join | 1 |
+| Spectate | 2 |
+
+### Activity Action Field Requirements
+
+If you want to hook up joining and spectating for your games, there are certain fields in the activity payload that need to be sent. Refer to the following handy table for what needs to be set for certain actions.
+
+
+
+
+| Field | Custom Artwork | Spectate | Join | Ask to Join |
+|--------------------------------|:--------------:|:--------:|:----:|:-----------:|
+| State | | | | |
+| Details | | | | |
+| ActivityTimestamps.Start | | | | |
+| ActivityTimestamps.End | | | | |
+| ActivityAssets.LargeImage | x | | | |
+| ActivityAssets.SmallImage | x | | | |
+| ActivityAssets.LargeText | x | | | |
+| ActivityAssets.SmallText | x | | | |
+| ActivityParty.Id | | | x | x |
+| ActivityParty.Size.CurrentSize | | | x | x |
+| ActivityParty.Size.MaxSize | | | x | x |
+| ActivitySecrets.Join | | | x | x |
+| ActivitySecrets.Spectate | | x | | |
+
+
+
+### Functions
+
+#### RegisterCommand
+
+Registers a command by which Discord can launch your game. This might be a custom protocol, like `my-awesome-game://`, or a path to an executable. It also supports any launch parameters that may be needed, like `game.exe --full-screen --no-hax`.
+
+On macOS, due to the way Discord registers executables, your game needs to be bundled for this command to work. That means it should be a `.app`.
+
+Returns `void`.
+
+###### Parameters
+
+| name | type | description |
+|---------|--------|-------------------------|
+| command | string | the command to register |
+
+###### Example
+
+```cs
+activityManager.RegisterCommand("my-awesome-game://run --full-screen");
+```
+
+#### RegisterSteam
+
+Used if you are distributing this SDK on Steam. Registers your game's Steam app id for the protocol `steam://run-game-id/`.
+
+Returns `void`.
+
+###### Parameters
+
+| name | type | description |
+|---------|--------|--------------------------|
+| steamId | UInt32 | your game's Steam app id |
+
+###### Example
+
+```cs
+activityManager.RegisterSteam(1938123);
+```
+
+#### UpdateActivity
+
+Sets a user's presence in Discord to a new activity. This has a rate limit of 5 updates per 20 seconds.
+
+> info
+> It is possible for users to hide their presence on Discord (User Settings -> Game Activity). Presence set through this SDK may not be visible when this setting is toggled off.
+
+Returns a `Discord.Result` via callback.
+
+###### Parameters
+
+| name | type | description |
+|----------|----------|-------------------------------|
+| activity | Activity | the new activity for the user |
+
+###### Example
+
+
+
+```cs
+var activity = new Discord.Activity
+{
+ State = "In Play Mode",
+ Details = "Playing the Trumpet!",
+ Timestamps =
+ {
+ Start = 5,
+ },
+ Assets =
+ {
+ LargeImage = "foo largeImageKey", // Larger Image Asset Value
+ LargeText = "foo largeImageText", // Large Image Tooltip
+ SmallImage = "foo smallImageKey", // Small Image Asset Value
+ SmallText = "foo smallImageText", // Small Image Tooltip
+ },
+ Party =
+ {
+ Id = "foo partyID",
+ Size = {
+ CurrentSize = 1,
+ MaxSize = 4,
+ },
+ },
+ Secrets =
+ {
+ Match = "foo matchSecret",
+ Join = "foo joinSecret",
+ Spectate = "foo spectateSecret",
+ },
+ Instance = true,
+};
+
+activityManager.UpdateActivity(activity, (result) =>
+{
+ if (result == Discord.Result.Ok)
+ {
+ Console.WriteLine("Success!");
+ }
+ else
+ {
+ Console.WriteLine("Failed");
+ }
+});
+```
+
+
+
+#### ClearActivity
+
+Clear's a user's presence in Discord to make it show nothing.
+
+Results a `Discord.Result` via callback.
+
+###### Example
+
+
+
+```cs
+activityManager.ClearActivity((result) =>
+{
+ if (result == Discord.Result.Ok)
+ {
+ Console.WriteLine("Success!");
+ }
+ else
+ {
+ Console.WriteLine("Failed");
+ }
+});
+```
+
+
+
+#### SendRequestReply
+
+Sends a reply to an Ask to Join request.
+
+Returns a `Discord.Result` via callback.
+
+###### Parameters
+
+| name | type | description |
+|--------|--------------------------|---------------------------------------------|
+| userId | Int64 | the user id of the person who asked to join |
+| reply | ActivityJoinRequestReply | No, Yes, or Ignore |
+
+###### Example
+
+
+
+```cs
+activityManager.OnActivityJoinRequest += user =>
+{
+ Console.WriteLine("Join request from: {0}", user.Id);
+ activityManager.SendRequestReply(user.Id, Discord.ActivityJoinRequestReply.Yes, (res) =>
+ {
+ if (res == Discord.Result.Ok)
+ {
+ Console.WriteLine("Responded successfully");
+ }
+ });
+}
+```
+
+
+#### SendInvite
+
+Sends a game invite to a given user. If you do not have a valid activity with all the required fields, this call will error. See [Activity Action Field Requirements](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activity-action-field-requirements) for the fields required to have join and spectate invites function properly.
+
+Returns a `Discord.Result` via callback.
+
+###### Parameters
+
+| name | type | description |
+|---------|--------------------|-------------------------------------------------------|
+| userId | Int64 | the id of the user to invite |
+| type | ActivityActionType | marks the invite as an invitation to join or spectate |
+| content | string | a message to send along with the invite |
+
+###### Example
+
+
+
+```cs
+var userId = 53908232506183680;
+activityManager.SendInvite(userId, Discord.ActivityActionType.Join, "Come play!", (result) =>
+{
+ if (result == Discord.Result.Ok)
+ {
+ Console.WriteLine("Success!");
+ }
+ else
+ {
+ Console.WriteLine("Failed");
+ }
+});
+```
+
+
+#### AcceptInvite
+
+Accepts a game invitation from a given userId.
+
+Returns a `Discord.Result` via callback.
+
+###### Parameters
+
+| name | type | description |
+|--------|-------|------------------------------------|
+| userId | Int64 | the id of the user who invited you |
+
+###### Example
+
+
+
+```cs
+activityManager.AcceptInvite(290926444748734466, (result) =>
+{
+ if (result == Discord.Result.Ok)
+ {
+ Console.WriteLine("Success!");
+ }
+ else
+ {
+ Console.WriteLine("Failed");
+ }
+});
+```
+
+
+### Events
+
+#### OnActivityJoin
+
+Fires when a user accepts a game chat invite or receives confirmation from Asking to Join.
+
+###### Parameters
+
+| name | type | description |
+|------------|--------|------------------------------------|
+| joinSecret | string | the secret to join the user's game |
+
+###### Example
+
+
+
+```cs
+// Received when someone accepts a request to join or invite.
+// Use secrets to receive back the information needed to add the user to the group/party/match
+activityManager.OnActivityJoin += secret => {
+ Console.WriteLine("OnJoin {0}", secret);
+ lobbyManager.ConnectLobbyWithActivitySecret(secret, (Discord.Result result, ref Discord.Lobby lobby) =>
+ {
+ Console.WriteLine("Connected to lobby: {0}", lobby.Id);
+ // Connect to voice chat, used in this case to actually know in overlay if your successful in connecting.
+ lobbyManager.ConnectVoice(lobby.Id, (Discord.Result voiceResult) => {
+
+ if (voiceResult == Discord.Result.Ok)
+ {
+ Console.WriteLine("New User Connected to Voice! Say Hello! Result: {0}", voiceResult);
+ }
+ else
+ {
+ Console.WriteLine("Failed with Result: {0}", voiceResult);
+ };
+ });
+ //Connect to given lobby with lobby Id
+ lobbyManager.ConnectNetwork(lobby.Id);
+ lobbyManager.OpenNetworkChannel(lobby.Id, 0, true);
+ foreach (var user in lobbyManager.GetMemberUsers(lobby.Id))
+ {
+ //Send a hello message to everyone in the lobby
+ lobbyManager.SendNetworkMessage(lobby.Id, user.Id, 0,
+ Encoding.UTF8.GetBytes(String.Format("Hello, {0}!", user.Username)));
+ }
+ //Sends this off to a Activity callback named here as 'UpdateActivity' passing in the discord instance details and lobby details
+ UpdateActivity(discord, lobby);
+ });
+};
+
+void UpdateActivity(Discord.Discord discord, Discord.Lobby lobby)
+ {
+ //Creates a Static String for Spectate Secret.
+ string discordSpectateSecret = "wdn3kvj320r8vk3";
+ spectateActivitySecret = discordSpectateSecret;
+ var activity = new Discord.Activity
+ {
+ State = "Playing Co-Op",
+ Details = "In a Multiplayer Match!",
+ Timestamps =
+ {
+ Start = startTimeStamp,
+ },
+ Assets =
+ {
+ LargeImage = "matchimage1",
+ LargeText = "Inside the Arena!",
+ },
+ Party = {
+ Id = lobby.Id.ToString(),
+ Size = {
+ CurrentSize = lobbyManager.MemberCount(lobby.Id),
+ MaxSize = (int)lobby.Capacity,
+ },
+ },
+ Secrets = {
+ Spectate = spectateActivitySecret,
+ Join = joinActivitySecret,
+ },
+ Instance = true,
+ };
+
+ activityManager.UpdateActivity(activity, result =>
+ {
+ Debug.LogFormat("Updated to Multiplayer Activity: {0}", result);
+
+ // Send an invite to another user for this activity.
+ // Receiver should see an invite in their DM.
+ // Use a relationship user's ID for this.
+ // activityManager
+ // .SendInvite(
+ // 364843917537050624,
+ // Discord.ActivityActionType.Join,
+ // "",
+ // inviteResult =>
+ // {
+ // Console.WriteLine("Invite {0}", inviteResult);
+ // }
+ // );
+ });
+ }
+```
+
+
+#### OnActivitySpectate
+
+Fires when a user accepts a spectate chat invite or clicks the Spectate button on a user's profile.
+
+###### Parameters
+
+| name | type | description |
+|----------------|--------|---------------------------------------------------|
+| spectateSecret | string | the secret to join the user's game as a spectator |
+
+###### Example
+
+
+
+```cs
+// Received when someone accepts a request to spectate
+activityManager.OnActivitySpectate += secret =>
+{
+ Console.WriteLine("OnSpectate {0}", secret);
+};
+```
+
+
+#### OnActivityJoinRequest
+
+Fires when a user asks to join the current user's game.
+
+###### Parameters
+
+| name | type | description |
+|------|------|-------------------------|
+| user | User | the user asking to join |
+
+###### Example
+
+
+
+```cs
+// A join request has been received. Render the request on the UI.
+activityManager.OnActivityJoinRequest += (ref Discord.User user) =>
+{
+ Console.WriteLine("OnJoinRequest {0} {1}", user.Username, user.Id);
+};
+```
+
+
+#### OnActivityInvite
+
+Fires when the user receives a join or spectate invite.
+
+###### Parameters
+
+| name | type | description |
+|----------|--------------------|--------------------------------------------|
+| type | ActivityActiontype | whether this invite is to join or spectate |
+| user | User | the user sending the invite |
+| activity | Activity | the inviting user's current activity |
+
+###### Example
+
+
+
+```cs
+// An invite has been received. Consider rendering the user / activity on the UI.
+activityManager.OnActivityInvite += (Discord.ActivityActionType Type, ref Discord.User user, ref Discord.Activity activity2) =>
+{
+ Console.WriteLine("Received Invite Type: {0}, from User: {1}, with Activity Name: {2}", Type, user.Username, activity2.Name);
+ // activityManager.AcceptInvite(user.Id, result =>
+ // {
+ // Console.WriteLine("AcceptInvite {0}", result);
+ // });
+};
+```
+
+
+### Inviting a User to a Game
+
+
+
+```cs
+var discord = new Discord.Discord(clientId, Discord.CreateFlags.Default);
+
+// Update user's activity for your game.
+// Party and secrets are vital.
+var activity = new Discord.Activity
+{
+ State = "olleh",
+ Details = "foo details",
+ Timestamps =
+ {
+ Start = 5,
+ End = 6,
+ },
+ Assets =
+ {
+ LargeImage = "foo largeImageKey",
+ LargeText = "foo largeImageText",
+ SmallImage = "foo smallImageKey",
+ SmallText = "foo smallImageText",
+ },
+ Party =
+ {
+ Id = "foo partyID",
+ Size = {
+ CurrentSize = 1,
+ MaxSize = 4,
+ },
+ },
+ Secrets =
+ {
+ Match = "foo matchSecret",
+ Join = "foo joinSecret",
+ Spectate = "foo spectateSecret",
+ },
+ Instance = true,
+};
+
+activityManager.UpdateActivity(activity, (result) =>
+{
+ Console.WriteLine("Update Activity {0}", result);
+
+ // Send an invite to another user for this activity.
+ // Receiver should see an invite in their DM.
+ // Use a relationship user's ID for this.
+ activityManager.SendInvite(364843917537050999, Discord.ActivityActionType.Join, "", (inviteUserResult) =>
+ {
+ Console.WriteLine("Invite User {0}", inviteUserResult);
+ });
+});
+```
+
+
+## Overlay
+
+> warn
+> The overlay is only supported on Windows for DirectX or OpenGL games. Linux, Mac, and games using Vulkan are not supported. [Click here for more info.](https://support.discord.com/hc/en-us/articles/217659737-Games-Overlay-101)
+
+Discord comes with an awesome built-in overlay, and you may want to make use of it for your game. This manager will help you do just that! It gives you the current state of the overlay for the user, and allows you to update that state.
+
+### Data Models
+
+#### ActivityActionType Enum
+
+| name | value |
+|----------|-------|
+| Join | 1 |
+| Spectate | 2 |
+
+### Functions
+
+#### IsEnabled
+
+Check whether the user has the overlay enabled or disabled. If the overlay is disabled, all the functionality in this manager will still work. The calls will instead focus the Discord client and show the modal there instead.
+
+Returns a `bool`.
+
+###### Example
+
+
+
+```cs
+if (!overlaymanager.IsEnabled())
+{
+ Console.WriteLine("Overlay is not enabled. Modals will be shown in the Discord client instead");
+}
+```
+
+
+#### IsLocked
+
+Check if the overlay is currently locked or unlocked
+
+###### Example
+
+
+
+```cs
+if (overlayManager.IsLocked())
+{
+ overlayManager.SetLocked(true, (res) =>
+ {
+ Console.WriteLine("Input in the overlay is now accessible again");
+ });
+}
+```
+
+
+#### SetLocked
+
+Locks or unlocks input in the overlay. Calling `SetLocked(true);` will also close any modals in the overlay or in-app from things like IAP purchase flows and disallow input.
+
+Returns `Discord.Result` via callback.
+
+###### Parameters
+
+| name | type | description |
+|--------|------|----------------------------|
+| locked | bool | lock or unlock the overlay |
+
+###### Example
+
+
+
+```cs
+overlayManager.SetLocked(true, (res) =>
+{
+ Console.WriteLine("Overlay has been locked and modals have been closed");
+});
+```
+
+
+
+#### OpenActivityInvite
+
+Opens the overlay modal for sending game invitations to users, channels, and servers. If you do not have a valid activity with all the required fields, this call will error. See [Activity Action Field Requirements](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activity-action-field-requirements) for the fields required to have join and spectate invites function properly.
+
+Returns a `Discord.Result` via callback.
+
+###### Parameters
+
+| name | type | description |
+|------|--------------------|-----------------------------|
+| type | ActivityActionType | what type of invite to send |
+
+###### Example
+
+
+
+```cs
+overlayManager.OpenActivityInvite(Discord.ActivityActionType.Join, (result) =>
+{
+ if (result == Discord.Result.Ok)
+ {
+ Console.WriteLine("User is now inviting others to play!");
+ }
+});
+```
+
+
+#### OpenGuildInvite
+
+Opens the overlay modal for joining a Discord guild, given its invite code. An invite code for a server may look something like `fortnite` for a verified server—the full invite being `discord.gg/fortnite`—or something like `rjEeUJq` for a non-verified server, the full invite being `discord.gg/rjEeUJq`.
+
+Returns a `Discord.Result` via callback. Note that a successful `Discord.Result` response does not necessarily mean that the user has joined the guild. If you want more granular control over and knowledge about users joining your guild, you may want to look into implementing the [`guilds.join` OAuth2 scope in an authorization code grant](#DOCS_TOPICS_OAUTH2/authorization-code-grant) in conjunction with the [Add Guild Members](#DOCS_RESOURCES_GUILD/add-guild-member) endpoint.
+
+###### Parameters
+
+| name | type | description |
+|------|--------|----------------------------|
+| code | string | an invite code for a guild |
+
+###### Example
+
+
+
+```cs
+overlayManager.OpenGuildInvite("rjEeUJq", (result) =>
+{
+ if (result == Discord.Result.Ok)
+ {
+ Console.WriteLine("Invite was valid.");
+ }
+});
+```
+
+
+#### OpenVoiceSettings
+
+Opens the overlay widget for voice settings for the currently connected application. These settings are unique to each user within the context of your application. That means that a user can have different favorite voice settings for each of their games!
+
+
+
+
+
+
+Also, when connected to a lobby's voice channel, the overlay will show a widget that allows users to locally mute, deafen, and adjust the volume of others.
+
+Returns a `Discord.Result` via callback.
+
+###### Example
+
+
+
+```cs
+overlayManager.OpenVoiceSettings((result) =>
+{
+ if (result == Discord.Result.Ok)
+ {
+ Console.WriteLine("Overlay is open to the voice settings for your application/")
+ }
+})
+```
+
+
+#### OnToggle
+
+Fires when the overlay is locked or unlocked (a.k.a. opened or closed)
+
+###### Parameters
+
+| name | type | description |
+|--------|------|---------------------------------------|
+| locked | bool | is the overlay now locked or unlocked |
+
+###### Example
+
+
+
+```cs
+overlayManager.OnToggle += overlayLock =>
+{
+ Console.WriteLine("Overlay Locked: {0}", overlayLock);
+};
+```
+
+
+#### Activate Overlay Invite Modal
+
+
+
+```cs
+var discord = new Discord.Discord(clientId, Discord.CreateFlags.Default);
+var overlayManager = discord.GetOverlayManager();
+
+// Invite users to join your game
+overlayManager.OpenActivityInvite(ActivityActionType.Join, (result) =>
+{
+ Console.WriteLine("Overlay is now open!");
+})
+```
+
+And that invite modal looks like this!
+
+
+
+
+
+## Relationships
+
+This manager helps you access the relationships your players have made on Discord. Unfortunately, it won't help them make relationships IRL. They're on their own for that. It lets you:
+
+- Access a user's relationships
+- Filter those relationships based on a given criteria
+- Build a user's friends list
+
+### Using the Relationships Manager
+
+Relationships on Discord change often; people start and stop playing games, go online, offline, invisible, or otherwise change state. Therefore, there are some important factors to remember when working with this manager. When you are first getting a list of a user's relationships, before you can `Filter()`, you need to wait for the `OnRefresh` callback to fire. This is your indicator that Discord has successfully taken a snapshot of the state of all your relationships at a given moment. Now that you have this snapshot, you can `Filter()` it to build the list that you want, and then iterate over that list to do whatever your game needs to do. Use this to build your initial social graph for a user.
+
+As relationships change, the `OnRelationshipUpdate` event will fire. You can use this to update the user's social graph, changing the status of the other Discord users that you chose to filter, e.g. someone is now online, or now playing the game, or no longer playing.
+
+Some examples can be found [below](#DOCS_DEVELOPER_TOOLS_GAME_SDK/creating-a-friends-list)
+
+### Data Models
+
+#### Relationship Struct
+
+| name | type | description |
+|----------|------------------|----------------------------------|
+| Type | RelationshipType | what kind of relationship it is |
+| User | User | the user the relationship is for |
+| Presence | Presence | that user's current presence |
+
+#### RelationshipType Enum
+
+| value | description |
+|-----------------|----------------------------------------------------------------------------------|
+| None | user has no intrinsic relationship |
+| Friend | user is a friend |
+| Blocked | user is blocked |
+| PendingIncoming | user has a pending incoming friend request to connected user |
+| PendingOutgoing | current user has a pending outgoing friend request to user |
+| Implicit | user is not friends, but interacts with current user often (frequency + recency) |
+
+#### Presence Struct
+
+| name | type | description |
+|----------|----------|----------------------------------|
+| Status | Status | the user's current online status |
+| Activity | Activity | the user's current activity |
+
+#### Status Enum
+
+| name | value |
+|--------------|-------|
+| Offline | 0 |
+| Online | 1 |
+| Idle | 2 |
+| DoNotDisturb | 3 |
+
+### Functions
+
+#### Filter
+
+Filters a user's relationship list by a boolean condition.
+
+Returns `void`.
+
+###### Parameters
+
+A function that takes a `Relationship` parameter.
+
+###### Example
+
+
+
+```cs
+relationshipsManager.Filter(relationship =>
+{
+ return relationship.Presence.Status == Discord.Status.Online;
+});
+```
+
+
+#### Get
+
+Get the relationship between the current user and a given user by id.
+
+Returns a `Relationship`.
+
+###### Parameters
+
+| name | type | description |
+|--------|-------|-----------------------------|
+| userId | Int64 | the id of the user to fetch |
+
+###### Example
+
+
+
+```cs
+var friend = relationshipsManager.Get(53908232506183680);
+Console.WriteLine("This is my friend, {0}", friend.User.Username);
+```
+
+
+#### GetAt
+
+Get the relationship at a given index when iterating over a list of relationships.
+
+Returns a `Relationship`.
+
+###### Parameters
+
+| name | type | description |
+|-------|--------|-------------------|
+| index | UInt32 | index in the list |
+
+###### Example
+
+
+
+```cs
+for (int i = 0; i < relationshipsManager.Count(); i++)
+{
+ var r = relationshipsManager.GetAt(i);
+ Console.WriteLine("This person is {0}", r.User.Username);
+}
+```
+
+
+#### Count
+
+Get the number of relationships that match your `Filter()`.
+
+Returns an `Int32`.
+
+###### Example
+
+
+
+```cs
+for (int i = 0; i < relationshipsManager.Count(); i++)
+{
+ var r = relationshipsManager.At(i);
+ Console.WriteLine("This person is {0}", r.User.Username);
+}
+```
+
+
+### Events
+
+#### OnRefresh
+
+Fires at initialization when Discord has cached a snapshot of the current status of all your relationships. Wait for this to fire before calling `Filter` within its callback.
+
+> warn
+> `OnRefresh` requires the `relationships.read` [OAuth2 scope](https://discord.com/developers/docs/topics/oauth2#shared-resources-oauth2-scopes). The Game SDK will return 0 relationships if the requested user has not authenticated with that scope.
+
+#### OnRelationshipUpdate
+
+Fires when a relationship in the filtered list changes, like an updated presence or user attribute.
+
+###### Parameters
+
+| name | type | description |
+|--------------|------------------|-------------------------------|
+| relationship | ref Relationship | the relationship that changed |
+
+###### Example
+
+
+
+```cs
+OnRelationshipUpdate += (ref Discord.Relationship relationship) =>
+{
+ Console.WriteLine("Who changed? {0}", relationship.User.Id);
+};
+```
+
+
+### Creating a Friends List
+
+
+
+```cs
+var discord = new Discord.Discord(clientId, Discord.CreateFlags.Default);
+var relationshipManager = discord.GetRelationshipManager();
+
+// Assign this handle right away to get the initial relationships update.
+// This callback will only be fired when the whole list is initially loaded or was reset
+
+// Wait for OnRefresh to fire to access a stable list
+// Filter a user's relationship list to be just friends
+// Use this list as your base
+relationshipManager.OnRefresh += () =>
+{
+ relationshipManager.Filter((relationship) =>
+ {
+ return relationship.Type == Discord.RelationshipType.Friend;
+ });
+
+ // Loop over all friends a user has.
+ Console.WriteLine("relationships updated: {0}", relationshipManager.Count());
+
+ for (var i = 0; i < relationshipManager.Count(); i++)
+ {
+ // Get an individual relationship from the list
+ var r = relationshipManager.GetAt((uint)i);
+ Console.WriteLine("relationships: {0} {1}", r.Type, r.User.Username);
+ // Save r off to a list of user's relationships
+ }
+}
+
+relationshipManager.OnRelationshipUpdate += (ref Discord.Relationship relationship) =>
+{
+ Console.WriteLine("User is {0}", relationship.User.Username);
+ // Update the matching user in your previously created list
+}
+```
+
+
+### Invite Users Who Are Playing the Same Game
+
+
+
+```cs
+var discord = new Discord.Discord(clientId, Discord.CreateFlags.Default);
+var relationshipManager = discord.GetRelationshipManager();
+var activityManager = discord.GetActivityManager();
+
+relationshipManager.OnRefresh += () =>
+{
+ relationshipManager.Filter((relationship) =>
+ {
+ // Filter for users who are playing the same game as the current user
+ // Is their activity application id the same as my client id?
+ return relationship.Presence.Activity.ApplicationId == clientId;
+ });
+
+ for (var i = 0; i < relationshipManager.Count(); i++)
+ {
+ // Get an individual relationship from the list
+ var r = relationshipManager.GetAt((uint)i);
+ Console.WriteLine("relationships: {0} {1}", r.Type, r.User.Username);
+
+ // Send them a game invite!
+ activityManager.InviteUser(r.User.Id, Discord.ActivityActionType.Join, "Come play with me!", (result) =>
+ {
+ Console.WriteLine("Invited user {0} to play with you", r.User.Username);
+ });
+ };
+}
+```
+
+
+## Users
+
+This manager helps retrieve basic user information for any user on Discord.
+
+### Data Models
+
+#### User Struct
+
+| name | type | description |
+|---------------|--------|-------------------------------|
+| Id | Int64 | the user's id |
+| Username | string | their name |
+| Discriminator | string | the user's unique discrim |
+| Avatar | string | the hash of the user's avatar |
+| Bot | bool | if the user is a bot user |
+
+#### UserFlag Enum
+
+| name | value | description |
+|-----------------|-------|------------------------------|
+| Partner | 2 | Discord Partner |
+| HypeSquadEvents | 4 | HypeSquad Events participant |
+| HypeSquadHouse1 | 64 | House Bravery |
+| HypeSquadHouse2 | 128 | House Brilliance |
+| HypeSquadHouse3 | 256 | House Balance |
+
+#### PremiumType Enum
+
+| name | value | description |
+|-------|-------|--------------------------|
+| None | 0 | Not a Nitro subscriber |
+| Tier1 | 1 | Nitro Classic subscriber |
+| Tier2 | 2 | Nitro subscriber |
+| Tier3 | 3 | Nitro Basic subscriber |
+
+### Functions
+
+#### GetCurrentUser
+
+> info
+> Before calling this function, you'll need to wait for the [OnCurrentUserUpdate](#DOCS_DEVELOPER_TOOLS_GAME_SDK/oncurrentuserupdate) callback to fire after instantiating the User manager.
+
+Fetch information about the currently connected user account. If you're interested in getting more detailed information about a user—for example, their email—check out our [GetCurrentUser](#DOCS_RESOURCES_USER/get-current-user) API endpoint. You'll want to call this with an authorization header of `Bearer `, where `` is the token retrieved from a standard [OAuth2 Authorization Code Grant](#DOCS_TOPICS_OAUTH2/authorization-code-grant) flow.
+
+Returns a `Discord.User`.
+
+###### Example
+
+
+
+```cs
+var user = userManager.GetCurrentUser();
+Console.WriteLine("Connected to user {0}", user.Id);
+```
+
+
+#### GetUser
+
+Get user information for a given id.
+
+Returns a `Discord.Result` and `ref Discord.User` via callback.
+
+###### Parameters
+
+| name | type | description |
+|--------|-------|-----------------------------|
+| userId | Int64 | the id of the user to fetch |
+
+###### Example
+
+
+
+```cs
+userManager.GetUser(userId, (Discord.Result result, ref Discord.User user) =>
+{
+ if (result == Discord.Result.Ok)
+ {
+ Console.WriteLine("User {0} is {1}", user.Id, user.Username);
+ }
+});
+```
+
+
+#### GetCurrentUserPremiumType
+
+Get the [PremiumType](#DOCS_DEVELOPER_TOOLS_GAME_SDK/premiumtype-enum) for the currently connected user.
+
+Returns `Discord.PremiumType`.
+
+###### Example
+
+
+
+```cs
+var userManager = discord.GetUserManager();
+var premiumType = userManager.GetCurrentUserPremiumType();
+switch (premiumType)
+{
+ case PremiumType.None:
+ Console.WriteLine("User is not a Nitro subscriber");
+
+ case PremiumType.Tier1:
+ Console.WriteLine("User has Nitro Classic");
+
+ case PremiumType.Tier2:
+ Console.WriteLine("User has Nitro");
+
+ default:
+ return;
+}
+```
+
+
+
+#### CurrentUserHasFlag
+
+See whether or not the current user has a certain [UserFlag](#DOCS_DEVELOPER_TOOLS_GAME_SDK/userflag-enum) on their account.
+
+Returns `bool`.
+
+###### Parameters
+
+| name | type | description |
+|------|----------------------------------------------------------|-----------------------------------------|
+| flag | [UserFlag](#DOCS_DEVELOPER_TOOLS_GAME_SDK/userflag-enum) | the flag to check on the user's account |
+
+###### Example
+
+
+
+```cs
+var userManager = discord.GetUserManager();
+if (userManager.CurrentUserHasFlag(Discord.UserFlag.HypeSquadHouse1))
+{
+ Console.WriteLine("User is a member of House Bravery!");
+}
+```
+
+
+
+### Events
+
+#### OnCurrentUserUpdate
+
+Fires when the `User` struct of the currently connected user changes. They may have changed their avatar, username, or something else.
+
+###### Example
+
+
+
+```cs
+var userManager = discord.GetUserManager();
+// GetCurrentUser will error until this fires once.
+userManager.OnCurrentUserUpdate += () => {
+ var currentUser = userManager.GetCurrentUser();
+
+ Console.WriteLine(currentUser.Username);
+ Console.WriteLine(currentUser.Id);
+ Console.WriteLine(currentUser.Discriminator);
+ Console.WriteLine(currentUser.Avatar);
+};
+```
+
+
+### Fetching Data About a Discord User
+
+
+
+```cs
+var discord = new Discord.Discord(clientId, Discord.CreateFlags.Default);
+
+var userManager = discord.GetUserManager();
+userManager.GetUser(450795363658366976, (Discord.Result result, ref Discord.User user) =>
+{
+ if (result == Discord.Result.Ok)
+ {
+ Console.WriteLine("user fetched: {0}", user.Username);
+ }
+ else
+ {
+ Console.WriteLine("user fetch error: {0}", result);
+ }
+});
+```
+
+
+## Store
+
+> danger
+> Selling SKUs and the purchase and discount features are deprecated. Some documentation has been removed to reflect this, but [the previous documentation in full can be viewed on GitHub](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Store.md)
+
+If your game has DLC or offers in-app purchases, this manager is for you! The Store Manager allows you to fetch a user's entitlements, as well as being notified when a user is granted an entitlement from a purchase flow for your game.
+
+### Data Models
+
+#### SKU Struct
+
+| name | type | description |
+|-------|----------|--------------------------|
+| Id | Int64 | the unique ID of the SKU |
+| Type | SkuType | what sort of SKU it is |
+| Name | string | the name of the SKU |
+| Price | SkuPrice | the price of the SKU |
+
+#### SkuType Enum
+
+| name | value | description |
+|-------------|-------|------------------------------------------------|
+| Application | 1 | SKU is a game |
+| DLC | 2 | SKU is a DLC |
+| Consumable | 3 | SKU is a consumable (in-app purchase) |
+| Bundle | 4 | SKU is a bundle (comprising the other 3 types) |
+
+#### SkuPrice Struct
+
+| name | type | description |
+|----------|--------|-----------------------------------|
+| Amount | UInt32 | the amount of money the SKU costs |
+| Currency | string | the currency the amount is in |
+
+#### Entitlement Struct
+
+| name | type | description |
+|-------|-----------------|-------------------------------------------------|
+| Id | Int64 | the unique ID of the entitlement |
+| Type | EntitlementType | the kind of entitlement it is |
+| SkuId | Int64 | the ID of the SKU to which the user is entitled |
+
+#### EntitlementType Enum
+
+| name | value | description |
+|---------------------|-------|----------------------------------------------------------------|
+| Purchase | 1 | entitlement was purchased |
+| PremiumSubscription | 2 | entitlement for a Discord Nitro subscription |
+| DeveloperGift | 3 | entitlement was gifted by a developer |
+| TestModePurchase | 4 | entitlement was purchased by a dev in application test mode |
+| FreePurchase | 5 | entitlement was granted when the SKU was free |
+| UserGift | 6 | entitlement was gifted by another user |
+| PremiumPurchase | 7 | entitlement was claimed by user for free as a Nitro Subscriber |
+
+#### Limited Payment Data Object
+
+| name | type | description |
+|---------------|--------|--------------------------------------|
+| id | string | unique ID of the payment |
+| currency | string | the currency the payment was made in |
+| amount | int | the amount paid |
+| tax | int | the amount of tax |
+| tax_inclusive | bool | whether the amount is tax-inclusive |
+
+### Functions
+
+#### FetchSkus
+
+Fetches the list of SKUs for the connected application, readying them for iteration.
+
+> warn
+> Only SKUs that have a price set will be fetched. If you aren't seeing any SKUs being returned, make sure they have a price set!
+
+Returns `Discord.Result` via callback.
+
+###### Example
+
+
+
+```cs
+storeManager.FetchSkus((result) =>
+{
+ if (result == Discord.Result.Ok)
+ {
+ Console.WriteLine("Got skus! Now I can iterate over them!");
+ }
+});
+```
+
+
+#### CountSkus
+
+Get the number of SKUs readied by `FetchSkus()`.
+
+Returns `Int32`.
+
+###### Example
+
+
+
+```cs
+for (int i = 0; i < storeManager.CountSkus(); i++)
+{
+ var sku = storeManager.GetSkuAt(i);
+ Console.WriteLine("Sku is {0}", sku.Name);
+}
+```
+
+
+
+#### GetSku
+
+Gets a SKU by its ID. You must call `FetchSkus()` first before being able to access SKUs in this way.
+
+Returns `Discord.Sku`.
+
+###### Parameters
+
+| name | type | description |
+|-------|-------|--------------------------|
+| skuId | Int64 | the ID of the SKU to get |
+
+###### Example
+
+
+
+```cs
+storeManager.FetchSkus((_) => {});
+var sku = storeManager.GetSku(276467180839763999);
+Console.WriteLine("Sku is {0}", sku.Name);
+```
+
+
+
+#### GetSkuAt
+
+Gets a SKU by index when iterating over SKUs. You must call `FetchSkus()` first before being able to access SKUs in this way.
+
+Returns `Discord.Sku`.
+
+###### Parameters
+
+| name | type | description |
+|-------|-------|---------------------------|
+| index | Int32 | the index at which to get |
+
+###### Example
+
+
+
+```cs
+storeManager.FetchSkus((result) =>
+{
+ for (int i = 0; i < storeManager.CountSkus(); i++)
+ {
+ var sku = storeManager.GetSkuAt(i);
+ Console.WriteLine("Sku is {0}", sku.Name);
+}
+});
+```
+
+
+
+#### FetchEntitlements
+
+Fetches a list of entitlements to which the user is entitled. Applications, DLC, and Bundles will always be returned. Consumables will be returned until they are consumed by the application via the HTTP endpoint.
+
+Returns `Discord.Result` via callback.
+
+###### Example
+
+
+
+```cs
+storeManager.FetchEntitlements((result) =>
+{
+ if (result == Discord.Result.Ok)
+ {
+ Console.WriteLine("Got entitlements!");
+ }
+});
+```
+
+
+
+#### CountEntitlements
+
+Get the number of entitlements readied by `FetchEntitlements()`. You must call `FetchEntitlements()` first before being able to access SKUs in this way.
+
+Returns `Int32`.
+
+###### Example
+
+
+
+```cs
+storeManager.FetchEntitlements((result) =>
+{
+ for (int i = 0; i < storeManager.CountEntitlements(); i++)
+ {
+ var entitlement = storeManager.GetEntitlementAt(i);
+ Console.WriteLine("Entitlement is {0}", entitlement.Name);
+ }
+});
+```
+
+
+#### GetEntitlement
+
+Gets an entitlement by its id. You must call `FetchEntitlements()` first before being able to access SKUs in this way.
+
+Returns `Discord.Entitlement`.
+
+###### Parameters
+
+| name | type | description |
+|---------------|-------|----------------------------------|
+| entitlementId | Int64 | the ID of the entitlement to get |
+
+###### Example
+
+
+
+```cs
+storeManager.FetchEntitlements((result) =>
+{
+ var entitlement = storeManager.GetEntitlement(276467180839763999);
+ Console.WriteLine("Entitlement is {0}", entitlement.Name);
+});
+```
+
+
+
+#### GetEntitlementAt
+
+Gets an entitlement by index when iterating over a user's entitlements. You must call `FetchEntitlements()` first before being able to access SKUs in this way.
+
+Returns `Discord.Entitlement`.
+
+###### Parameters
+
+| name | type | description |
+|-------|-------|---------------------------|
+| index | Int32 | the index at which to get |
+
+###### Example
+
+
+
+```cs
+storeManager.FetchEntitlements((result) =>
+{
+ for (int i = 0; i < storeManager.CountEntitlements(); i++)
+ {
+ var entitlement = storeManager.GetEntitlementAt(i);
+ Console.WriteLine("Entitlement is {0}", entitlement.Name);
+ }
+});
+```
+
+
+
+#### HasSkuEntitlement
+
+Returns whether or not the user is entitled to the given SKU ID. You must call `FetchEntitlements()` first before being able to access SKUs in this way.
+
+Returns `bool`.
+
+###### Parameters
+
+| name | type | description |
+|-------|-------|----------------------------|
+| skuId | Int64 | the ID of the SKU to check |
+
+###### Example
+
+
+
+```cs
+storeManager.FetchEntitlements((result) =>
+{
+ if (storeManager.HasSkuEntitlement(276467180839763999))
+ {
+ Console.WriteLine("User has entitlement to this SKU");
+ }
+ else
+ {
+ Console.WriteLine("How are you even running this right now...");
+ }
+});
+```
+
+
+
+### Events
+
+#### OnEntitlementCreate
+
+Fires when the connected user receives a new entitlement, either through purchase or through a developer grant.
+
+###### Parameters
+
+| name | type | description |
+|-------------|---------------------|-------------------------------------------|
+| entitlement | Discord.Entitlement | the entitlement the user has been granted |
+
+#### OnEntitlementDelete
+
+Fires when the connected user loses an entitlement, either by expiration, revocation, or consumption in the case of consumable entitlements.
+
+###### Parameters
+
+| name | type | description |
+|-------------|---------------------|-----------------------------------|
+| entitlement | Discord.Entitlement | the entitlement the user has lost |
+
+### HTTP Endpoints
+
+The following are HTTP requests, and should be handled by your game server (rather than a client). You can refer to the [reference documentation](#DOCS_REFERENCE/authentication) for information on authenticating HTTP requests using your app's bot token.
+
+#### Get Entitlements % GET /applications/\{application.id#DOCS_DEVELOPER_TOOLS_GAME_SDK/getting-started\}/entitlements
+
+Gets entitlements for a given user. You can use this on your game backend to check entitlements of an arbitrary user, or perhaps in an administrative panel for your support team.
+
+###### Query String Params
+
+| name | type | description |
+|----------------|--------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|
+| user_id? | snowflake | the user id to look up entitlements for
+| sku_ids? | comma-delimited set of snowflakes | (optional) the list SKU ids to check entitlements for |
+| with_payments? | [boolean](#DOCS_REFERENCE/boolean-query-strings) | returns [limited payment data](#DOCS_DEVELOPER_TOOLS_GAME_SDK/limited-payment-data-object) for each entitlement |
+| before? | snowflake | retrieve entitlements before this time |
+| after? | snowflake | retrieve entitlements after this time |
+| limit? | int | number of entitlements to return, 1-100, default 100 |
+| guild_id? | snowflake | the guild id to look up entitlements for |
+| exclude_ended? | [boolean](#DOCS_REFERENCE/boolean-query-strings) | whether or not ended entitlements should be omitted |
+
+###### Example
+
+
+
+```
+curl https://discord.com/api/v6/applications/461618159171141643/entitlements?user_id=53908232506183680&sku_ids=53908232599983680&with_payments=true&limit=1 \
+-H "Authorization: Bearer " \
+-H "Accept: application/json"
+
+// Returns
+
+{
+ [
+ {
+ "user_id": "53908232506183680",
+ "sku_id": "53908232599983680",
+ "application_id": "461618159171141643",
+ "id": "53908232506183999",
+ "type": 1,
+ "payment": {
+ "id": "538491076055400999",
+ "currency": "usd",
+ "amount": 999,
+ "tax": 0,
+ "tax_inclusive": false
+ }
+ }
+ ]
+}
+```
+
+
+#### Get Entitlement % GET /applications/\{application.id#DOCS_DEVELOPER_TOOLS_GAME_SDK/getting-started\}/entitlements/\{entitlement.id#DOCS_DEVELOPER_TOOLS_GAME_SDK/entitlement-struct\}
+
+Fetch an entitlement by its ID. This may be useful in confirming that a user has a given entitlement that another call or the SDK says they do.
+
+###### Query String Params
+
+| name | type | description |
+|---------------|--------------------------------------------------|-----------------------------------------------------------------------------------------------------------------|
+| with_payment? | [boolean](#DOCS_REFERENCE/boolean-query-strings) | returns [limited payment data](#DOCS_DEVELOPER_TOOLS_GAME_SDK/limited-payment-data-object) for each entitlement |
+
+###### Example
+
+
+
+```
+curl https://discord.com/api/v6/applications/461618159171141643/entitlements/53908232506183999?with_payment=true \
+-H "Authorization: Bearer " \
+-H "Accept: application/json"
+
+// Returns
+
+{
+ "user_id": "53908232506183680",
+ "sku_id": "53908232599983680",
+ "application_id": "461618159171141643",
+ "id": "53908232506183999",
+ "type": 3,
+ "payment": {
+ "id": "538491076055400999",
+ "currency": "usd",
+ "amount": 999,
+ "tax": 0,
+ "tax_inclusive": false
+ }
+}
+```
+
+
+#### Get SKUs % GET /applications/\{application.id#DOCS_DEVELOPER_TOOLS_GAME_SDK/getting-started\}/skus
+
+Get all SKUs for an application.
+
+###### Example
+
+
+
+```
+curl https://discord.com/api/v6/applications/461618159171141643/skus \
+-H "Authorization: Bearer " \
+-H "Accept: application/json"
+
+// Returns
+
+{
+ [
+ {
+ "id": "53908232599983680",
+ "type": 1,
+ "dependent_sku_id": null,
+ "application_id": "461618159171141643",
+ "manifest_labels": ["461618159171111111"],
+ "name": "My Awesome Test Game",
+ "access_type": 1,
+ "features": [1, 2, 3],
+ "system_requirements": {},
+ "content_ratings": {},
+ "release_date": "1999-01-01",
+ "legal_notice": {},
+ "price_tier": 1099,
+ "price": {},
+ "premium": false,
+ "locales": ["en-US"],
+ "bundled_skus": null
+ }
+ ]
+}
+```
+
+
+
+## Deprecated
+
+> danger
+> The following Game SDK managers have been deprecated. In each section, we link to the previous documentation for each of the managers on GitHub, but generally these features shouldn't be used and may be decommissioned without notice.
+
+### Achievements
+
+There's no feeling quite like accomplishing a goal that you've set out to achieve. Is killing 1000 zombies in a game as great an achievement as climbing Mt. Everest? Of course it is, and I didn't even have to leave my house. So get off my back, society.
+
+Anyway—Discord has achievements! Show your players just how successful they are.
+
+[Achievements Manager documentation on GitHub](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Achievements.md)
+
+### Applications
+
+> info
+> If you're looking for information about Discord apps, you can read the [Applications](#DOCS_RESOURCES_APPLICATION)
+
+The Applications manager gives you access to a bearer token for the currently connected Discord user, which you can send off to your server to do user authentication.
+
+[Application Manager documentation on GitHub](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Applications.md)
+
+### Voice
+
+The Voice manager can help integrate voice with your game! Note that the main functionality for voice in this SDK is not _only_ in this manager. Connecting players to a voice chat happens with [ConnectVoice](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Lobbies.md#connectvoice) in the Lobby manager, and robust voice settings work through [OpenVoiceSettings](#DOCS_DEVELOPER_TOOLS_GAME_SDK/openvoicesettings) in the Overlay manager.
+
+The Voice manager handles a few fine-grain details like self muting/deafening, swapping between VAD/PTT voice modes, and setting a PTT key. It's a subset of the robust settings from the overlay call for those of you that prefer to build UI and control things from your own game.
+
+[Voice Manager documentation on GitHub](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Discord_Voice.md)
+
+### Images
+
+Discord is like a book; it's better with pictures. The image manager helps you fetch image data for images in Discord, including user's avatars. They worked hard to pick out those photos and gifs. Show them you care, too.
+
+[Image Manager documentation on GitHub](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Images.md)
+
+### Lobbies
+
+Lobbies are a great way to organize players into contexts to play together. This manager works hand in hand with the networking layer of our SDK to make multiplayer integrations a breeze.
+
+[Lobby Manager documentation on GitHub](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Lobbies.md)
+
+### Networking
+
+Need a networking layer? Have a networking layer! This manager handles all things packets so you can get data from player to player and make your multiplayer...work.
+
+[Networking Manager docs on GitHub](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Networking.md)
+
+### Storage
+
+The Storage manager lets you save data mapped to a key for easy reading, writing, and deleting both synchronously and asynchronously. It's saved to a super special directory, the Holy Grail of file mappings, that's unique per Discord user — no need to worry about your little brother overwriting your save file.
+
+Creating this manager will also spawn an IO thread for async reads and writes, so unless you really want to be blocking, you don't need to be!
+
+[Storage Manager documentation on GitHub](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Storage.md)
diff --git a/docs/game_sdk/Achievements.md b/docs/game_sdk/Achievements.md
deleted file mode 100644
index fd18b1173f..0000000000
--- a/docs/game_sdk/Achievements.md
+++ /dev/null
@@ -1,389 +0,0 @@
-# Achievements
-
-> info
-> Need help with the SDK? Talk to us in the [Discord Developers Server](https://discord.gg/discord-developers)!
-
-> danger
-> Selling SKUs on Discord has now been discontinued as of March 1, 2022. [Read here for more info.](https://support-dev.discord.com/hc/en-us/articles/6309018858647-Self-serve-Game-Selling-Deprecation)
-
-> danger
-> The GameSDK's Achievements, Applications, Voice, Images, Lobbies, Networking, Storage, and Store (purchases and discounts) features have been deprecated, and will be decommissioned on **May 2, 2023**. [Read more](#DOCS_CHANGE_LOG/gamesdk-feature-deprecation)
-
-There's no feeling quite like accomplishing a goal that you've set out to achieve. Is killing 1000 zombies in a game as great an achievement as climbing Mt. Everest? Of course it is, and I didn't even have to leave my house. So get off my back, society.
-
-Anyway—Discord has achievements! Show your players just how successful they are.
-
-Achievements are managed in the [Developer Portal](https://discord.com/developers/applications). Head over to your application --> `Achievements` to create and manage achievements for your game. You'll give them an icon, a name, and a description; then they'll be assigned an id.
-
-You can also mark achievements as `secret` and `secure`. "Secret" achievements will _not_ be shown to the user until they've unlocked them. "Secure" achievements can only be set via HTTP calls from your server, _not_ by a game client using the SDK. No cheaters here!
-
-## Data Models
-
-###### Achievement Struct
-
-| name | type | description |
-|---------------------------|-----------------------------------------------------------------------|------------------------------------------------------|
-| application_id | Int64 | Unique ID of the application |
-| name | string | Name of the achievement |
-| name_localizations | ?dictionary with keys as [available locales](#DOCS_REFERENCE/locales) | Localization dictionary for the `name` field |
-| description | string | Description of the achievement |
-| description_localizations | ?dictionary with keys as [available locales](#DOCS_REFERENCE/locales) | Localization dictionary for the `description` field |
-| secret | boolean | If the achievement is secret |
-| secure | boolean | If the achievement is secure |
-| id | Int64 | Unique ID of the achievement |
-| icon_hash | string | [Hash of the icon](#DOCS_REFERENCE/image-formatting) |
-
-###### User Achievement Struct
-
-| name | type | description |
-|-----------------|--------|--------------------------------------------------------------------------------------------|
-| UserId | Int64 | the unique ID of the user working on the achievement |
-| AchievementId | Int64 | the unique ID of the achievement |
-| PercentComplete | UInt8 | how far along the user is to completing the achievement (0-100) |
-| UnlockedAt | string | the timestamp at which the user completed the achievement (PercentComplete was set to 100) |
-
-## SetUserAchievement
-
-Updates the current user's status for a given achievement. If `percentComplete` is set to `100`, the `UnlockedAt` field will be automatically updated with the current timestamp.
-
-Returns `Discord.Result` via callback.
-
-###### Parameters
-
-| name | type | description |
-|-----------------|-------|----------------------------------------|
-| achievementId | Int64 | the ID of the achievement to update |
-| percentComplete | UInt8 | the user's updated percentage progress |
-
-###### Example
-
-```cs
-achievementManager.SetUserAchievement(580159119969878046, 25, (res) =>
-{
- if (res == Discord.Result.Ok)
- {
- Console.WriteLine("Achievement updated for user");
- }
-});
-```
-
-## FetchUserAchievements
-
-Loads a stable list of the current user's achievements to iterate over. If the user has any achievements, do your iteration within the callback of this function.
-
-Returns `Discord.Result` via callback.
-
-> info
-> Remember to only iterate when there are results!
-
-###### Parameters
-
-None.
-
-###### Example
-
-```cs
-achievementManager.FetchUserAchievements((res) =>
-{
- if (res == Discord.Result.Ok)
- {
- // Count()
- // for() loop
- }
-});
-```
-
-## CountUserAchievements
-
-Counts the list of a user's achievements for iteration.
-
-Returns `Int32`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-achievementManager.FetchUserAchievements((res) =>
-{
- if (res == Discord.Result.Ok)
- {
- Console.WriteLine("User has {0} achievements for this game", achievementManager.CountUserAchievements());
- }
-});
-```
-
-## GetUserAchievementAt
-
-Gets the user's achievement at a given index of their list of achievements.
-
-Returns `Discord.UserAchievement`
-
-###### Parameters
-
-| name | type | description |
-|-------|-------|-------------------------------------------|
-| index | Int32 | the index at which to get the achievement |
-
-###### Example
-
-```cs
-achievementManager.FetchUserAchievements((res) =>
-{
- if (res == Discord.Result.Ok)
- {
- for (int i = 0; i < achievementManager.CountUserAchievements(); i++)
- {
- var achievement = achievementManager.GetUserAchievementAt(i);
- Console.WriteLine("Achievement progress for {0} for user {1}: {2}",
- achievement.AchievementId,
- achievement.UserId,
- achievement.PercentComplete);
- }
- }
-});
-```
-
-## GetUserAchievement
-
-Gets the user achievement for the given achievement id. If you keep a hardcoded mapping of `achievement <--> ID` in your codebase, this will be better than iterating over each achievement. Make sure to call `FetchUserAchievements()` first still!
-
-###### Parameters
-
-| name | type | description |
-|---------------|-------|----------------------------------|
-| achievementId | Int64 | the ID of the achievement to get |
-
-###### Example
-
-```cs
-achievementManager.FetchUserAchievements((res) =>
-{
- if (res == Discord.Result.Ok)
- {
- var achievement = achievementManager.GetUserAchievement(580159119969878046);
- Console.WriteLine("Achievement progress for {0} for user {1}: {2}",
- achievement.AchievementId,
- achievement.UserId,
- achievement.PercentComplete);
- }
-});
-```
-
-## OnUserAchievementUpdate
-
-Fires when an achievement is updated for the currently connected user
-
-###### Parameters
-
-| name | type | description |
-|-------------|---------------------|----------------------------------|
-| achievement | ref UserAchievement | the achievement that was updated |
-
-## The API Way
-
-Below are the API endpoints and the parameters they accept. If you choose to interface directly with the Discord API, you will need a bot token. This is a special authorization token with which your application can access Discord's HTTP API. Head on over to [your app's settings](https://discord.com/developers/applications), and navigate to the **Bot** page on the sidebar. From there, mutter _abra kadabra_ and reveal the token. This token is used as an authorization header against our API like so:
-
-```
-curl -x POST -h "Authorization: Bot " https://discord.com/api/some-route/that-does-a-thing
-```
-
-> info
-> Make sure to prepend your token with "Bot"!
-
-## Get Achievements % GET /applications/{application.id#DOCS_GAME_SDK_GETTING_STARTED/get-set-up}/achievements
-
-Returns all achievements for the given application. This endpoint has a rate limit of 5 requests per 5 seconds per application.
-
-###### Return Object
-
-```json
-[
- {
- "application_id": "461618159171141643",
- "name": {
- "default": "Win the Game"
- },
- "description": {
- "default": "You won!"
- },
- "secret": false,
- "icon_hash": "52c1636444f64ad7cb5368b158847def",
- "id": "580159119969878046",
- "secure": false
- }
-]
-```
-
-## Get Achievement % GET /applications/{application.id#DOCS_GAME_SDK_GETTING_STARTED/get-set-up}/achievements/{achievement.id#DOCS_GAME_SDK_ACHIEVEMENTS/data-models-achievement-struct}
-
-Returns the given achievement for the given application. This endpoint has a rate limit of 5 requests per 5 seconds per application.
-
-###### Return Object
-
-```json
-{
- "application_id": "461618159171141643",
- "name": {
- "default": "Win the Game"
- },
- "description": {
- "default": "You won!"
- },
- "secret": false,
- "icon_hash": "52c1636444f64ad7cb5368b158847def",
- "id": "580159119969878046",
- "secure": false
-}
-```
-
-## Create Achievement % POST /applications/{application.id#DOCS_GAME_SDK_GETTING_STARTED/get-set-up}/achievements
-
-Creates a new achievement for your application. Applications can have a maximum of 1000 achievements. This endpoint has a rate limit of 5 requests per 5 seconds per application.
-
-###### Parameters
-
-| name | type | description |
-|-------------|-----------|-----------------------------------------|
-| name | string | the name of the achievement |
-| description | string | the user-facing achievement description |
-| secret | bool | if the achievement is secret |
-| secure | bool | if the achievement is secure |
-| icon | ImageType | the icon for the achievement |
-
-###### Example: Creating an Achievement
-
-```json
-{
- "name": {
- "default": "Find the Secret"
- },
- "description": {
- "default": "You found it!"
- },
- "secret": true,
- "secure": false,
- "icon": "data:image/png;base64,base64_data_here"
-}
-```
-
-###### Return Object
-
-```json
-{
- "application_id": "461618159171141643",
- "name": {
- "default": "Find the Secret"
- },
- "description": {
- "default": "You found it!"
- },
- "secret": true,
- "icon_hash": "52c1636444f64ad7cb5368b158847def",
- "id": "597763781871861018",
- "secure": false
-}
-```
-
-## Update Achievement % PATCH /applications/{application.id#DOCS_GAME_SDK_GETTING_STARTED/get-set-up}/achievements/{achievement.id#DOCS_GAME_SDK_ACHIEVEMENTS/data-models-achievement-struct}
-
-Updates the achievement for **\_\_ALL USERS\_\_**. This is **NOT** to update a single user's achievement progress; this is to edit the UserAchievement itself. This endpoint has a rate limit of 5 requests per 5 seconds per application.
-
-###### Parameters
-
-| name | type | description |
-|-------------|-----------|-----------------------------------------|
-| name | string | the name of the achievement |
-| description | string | the user-facing achievement description |
-| secret | bool | if the achievement is secret |
-| secure | bool | if the achievement is secure |
-| icon | ImageType | the icon for the achievement |
-
-###### Example: Updating an Achievement
-
-```json
-{
- "name": {
- "default": "How do methods break up?"
- },
- "description": {
- "default": "They stop calling each other!"
- },
- "secret": false,
- "secure": false,
- "icon": "data:image/png;base64,base64_data_here"
-}
-```
-
-###### Return Object
-
-```json
-{
- "application_id": "461618159171141643",
- "name": {
- "default": "How do methods break up?"
- },
- "description": {
- "default": "They stop calling each other!"
- },
- "secret": false,
- "icon_hash": "7d698b594c691e3d28c92e226b28293c",
- "id": "597638720379682816",
- "secure": false
-}
-```
-
-## Delete Achievement % DELETE /applications/{application.id#DOCS_GAME_SDK_GETTING_STARTED/get-set-up}/achievements/{achievement.id#DOCS_GAME_SDK_ACHIEVEMENTS/data-models-achievement-struct}
-
-Deletes the given achievement from your application. This endpoint has a rate limit of 5 requests per 5 seconds per application.
-
-###### Return Object
-
-```json
-// 204 No Content
-```
-
-## Update User Achievement % PUT /users/{user.id#DOCS_RESOURCES_USER/user-object}/applications/{application.id#DOCS_GAME_SDK_GETTING_STARTED/get-set-up}/achievements/{achievement.id#DOCS_GAME_SDK_ACHIEVEMENTS/data-models-achievement-struct}
-
-Updates the UserAchievement record for a given user. Use this endpoint to update `secure` achievement progress for users. This endpoint has a rate limit of 5 requests per 5 seconds per application.
-
-###### Parameters
-
-| name | type | description |
-|------------------|------|--------------------------------------------------------|
-| percent_complete | int | the user's progress towards completing the achievement |
-
-###### Return Object
-
-```json
-{}
-```
-
-## Get User Achievements % GET /users/@me/applications/{application.id#DOCS_GAME_SDK_GETTING_STARTED/get-set-up}/achievements
-
-Returns a list of achievements for the user whose token you're making the request with. This endpoint will **NOT** accept the Bearer token for your application generated via the [Client Credentials Grant](#DOCS_TOPICS_OAUTH2/client-credentials-grant). You will need the _user's_ bearer token, gotten via either the [Authorization Code OAuth2 Grant](#DOCS_TOPICS_OAUTH2/authorization-code-grant) or via the SDK with [GetOAuth2Token](#DOCS_GAME_SDK_APPLICATIONS/getoauth2token). This endpoint has a rate limit of 2 requests per 5 seconds per application per user.
-
-> info
-> This endpoint will _not_ return any achievements marked as `secret` that the user has not yet completed.
-
-###### Return Object
-
-```json
-[
- {
- "application_id": "461618159171141643",
- "name": {
- "default": "Win the Game"
- },
- "description": {
- "default": "You won!"
- },
- "secret": false,
- "icon_hash": "52c1636444f64ad7cb5368b158847def",
- "id": "580159119969878046",
- "secure": false
- }
-]
-```
diff --git a/docs/game_sdk/Activities.md b/docs/game_sdk/Activities.md
deleted file mode 100644
index e119ba118c..0000000000
--- a/docs/game_sdk/Activities.md
+++ /dev/null
@@ -1,558 +0,0 @@
-# Activities
-
-> info
-> Need help with the SDK? Talk to us in the [Discord Developers Server](https://discord.gg/discord-developers)!
-
-Looking to integrate Rich Presence into your game? No need to manage multiple SDKs—this one does all that awesome stuff, too!. Delight your players with the ability to post game invites in chat and party up directly from Discord. Surface interesting live game data in their profile and on the Games Tab for their friends, encouraging them to group up and play together.
-
-For more detailed information and documentation around the Rich Presence feature set and integration tips, check out our [Rich Presence Documentation](https://discord.com/developers/docs/rich-presence/how-to).
-
-## Data Models
-
-###### User Struct
-
-| name | type | description |
-|---------------|--------|-------------------------------|
-| Id | Int64 | the user's id |
-| Username | string | their name |
-| Discriminator | string | the user's unique discrim |
-| Avatar | string | the hash of the user's avatar |
-| Bot | bool | if the user is a bot user |
-
-###### Activity Struct
-
-| name | type | description |
-|---------------|--------------------|-----------------------------------------------------------------|
-| ApplicationId | Int64 | your application id - this is a read-only field |
-| Name | string | name of the application - this is a read-only field |
-| State | string | the player's current party status |
-| Details | string | what the player is currently doing |
-| Timestamps | ActivityTimestamps | helps create elapsed/remaining timestamps on a player's profile |
-| Assets | ActivityAssets | assets to display on the player's profile |
-| Party | ActivityParty | information about the player's party |
-| Secrets | ActivitySecrets | secret passwords for joining and spectating the player's game |
-| Instance | bool | whether this activity is an instanced context, like a match |
-
-###### ActivityTimestamps Struct
-
-| name | type | description |
-|-------|-------|--------------------------------------------------------|
-| Start | Int64 | unix timestamp - send this to have an "elapsed" timer |
-| End | Int64 | unix timestamp - send this to have a "remaining" timer |
-
-###### ActivityAssets Struct
-
-| name | type | description |
-|------------|--------|----------------------------------------------------------------------------------------------|
-| LargeImage | string | see [Activity Asset Image](#DOCS_TOPICS_GATEWAY_EVENTS/activity-object-activity-asset-image) |
-| LargeText | string | hover text for the large image |
-| SmallImage | string | see [Activity Asset Image](#DOCS_TOPICS_GATEWAY_EVENTS/activity-object-activity-asset-image) |
-| SmallText | string | hover text for the small image |
-
-###### ActivityParty Struct
-
-| name | type | description |
-|------|-----------|------------------------------------|
-| Id | string | a unique identifier for this party |
-| Size | PartySize | info about the size of the party |
-
-###### PartySize Struct
-
-| name | type | description |
-|-------------|-------|------------------------------------|
-| CurrentSize | Int32 | the current size of the party |
-| MaxSize | Int32 | the max possible size of the party |
-
-###### ActivitySecrets Struct
-
-| name | type | description |
-|----------|--------|----------------------------------------------|
-| Match | string | unique hash for the given match context |
-| Join | string | unique hash for chat invites and Ask to Join |
-| Spectate | string | unique hash for Spectate button |
-
-###### ActivityType Enum
-
-| name | Value |
-|-----------|-------|
-| Playing | 0 |
-| Streaming | 1 |
-| Listening | 2 |
-| Watching | 3 |
-| Custom | 4 |
-| Competing | 5 |
-
-For more details about the activity types, [see Gateway documentation](#DOCS_TOPICS_GATEWAY_EVENTS//activity-object-activity-types).
-
-`ActivityType` is strictly for the purpose of handling events that you receive from Discord; though the SDK will not reject a payload with an `ActivityType` sent, it will be discarded and will not change anything in the client.
-
-###### ActivityJoinRequestReply Enum
-
-| name | value |
-|--------|-------|
-| No | 0 |
-| Yes | 1 |
-| Ignore | 2 |
-
-###### ActivityActionType Enum
-
-| name | value |
-|----------|-------|
-| Join | 1 |
-| Spectate | 2 |
-
-## Activity Action Field Requirements
-
-If you want to hook up joining and spectating for your games, there are certain fields in the activity payload that need to be sent. Refer to the following handy table for what needs to be set for certain actions.
-
-###### Requirements
-
-| Field | Custom Artwork | Spectate | Join | Ask to Join |
-|--------------------------------|:--------------:|:--------:|:----:|:-----------:|
-| State | | | | |
-| Details | | | | |
-| ActivityTimestamps.Start | | | | |
-| ActivityTimestamps.End | | | | |
-| ActivityAssets.LargeImage | x | | | |
-| ActivityAssets.SmallImage | x | | | |
-| ActivityAssets.LargeText | x | | | |
-| ActivityAssets.SmallText | x | | | |
-| ActivityParty.Id | | | x | x |
-| ActivityParty.Size.CurrentSize | | | x | x |
-| ActivityParty.Size.MaxSize | | | x | x |
-| ActivitySecrets.Join | | | x | x |
-| ActivitySecrets.Spectate | | x | | |
-
-## RegisterCommand
-
-Registers a command by which Discord can launch your game. This might be a custom protocol, like `my-awesome-game://`, or a path to an executable. It also supports any launch parameters that may be needed, like `game.exe --full-screen --no-hax`.
-
-On macOS, due to the way Discord registers executables, your game needs to be bundled for this command to work. That means it should be a `.app`.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|---------|--------|-------------------------|
-| command | string | the command to register |
-
-###### Example
-
-```cs
-activityManager.RegisterCommand("my-awesome-game://run --full-screen");
-```
-
-## RegisterSteam
-
-Used if you are distributing this SDK on Steam. Registers your game's Steam app id for the protocol `steam://run-game-id/`.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|---------|--------|--------------------------|
-| steamId | UInt32 | your game's Steam app id |
-
-###### Example
-
-```cs
-activityManager.RegisterSteam(1938123);
-```
-
-## UpdateActivity
-
-Sets a user's presence in Discord to a new activity. This has a rate limit of 5 updates per 20 seconds.
-
-> info
-> It is possible for users to hide their presence on Discord (User Settings -> Game Activity). Presence set through this SDK may not be visible when this setting is toggled off.
-
-Returns a `Discord.Result` via callback.
-
-###### Parameters
-
-| name | type | description |
-|----------|----------|-------------------------------|
-| activity | Activity | the new activity for the user |
-
-###### Example
-
-```cs
-var activity = new Discord.Activity
-{
- State = "In Play Mode",
- Details = "Playing the Trumpet!",
- Timestamps =
- {
- Start = 5,
- },
- Assets =
- {
- LargeImage = "foo largeImageKey", // Larger Image Asset Value
- LargeText = "foo largeImageText", // Large Image Tooltip
- SmallImage = "foo smallImageKey", // Small Image Asset Value
- SmallText = "foo smallImageText", // Small Image Tooltip
- },
- Party =
- {
- Id = "foo partyID",
- Size = {
- CurrentSize = 1,
- MaxSize = 4,
- },
- },
- Secrets =
- {
- Match = "foo matchSecret",
- Join = "foo joinSecret",
- Spectate = "foo spectateSecret",
- },
- Instance = true,
-};
-
-activityManager.UpdateActivity(activity, (result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Success!");
- }
- else
- {
- Console.WriteLine("Failed");
- }
-});
-```
-
-## ClearActivity
-
-Clear's a user's presence in Discord to make it show nothing.
-
-Results a `Discord.Result` via callback.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-activityManager.ClearActivity((result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Success!");
- }
- else
- {
- Console.WriteLine("Failed");
- }
-});
-```
-
-## SendRequestReply
-
-Sends a reply to an Ask to Join request.
-
-Returns a `Discord.Result` via callback.
-
-###### Parameters
-
-| name | type | description |
-|--------|--------------------------|---------------------------------------------|
-| userId | Int64 | the user id of the person who asked to join |
-| reply | ActivityJoinRequestReply | No, Yes, or Ignore |
-
-###### Example
-
-```cs
-activityManager.OnActivityJoinRequest += user =>
-{
- Console.WriteLine("Join request from: {0}", user.Id);
- activityManager.SendRequestReply(user.Id, Discord.ActivityJoinRequestReply.Yes, (res) =>
- {
- if (res == Discord.Result.Ok)
- {
- Console.WriteLine("Responded successfully");
- }
- });
-}
-```
-
-## SendInvite
-
-Sends a game invite to a given user. If you do not have a valid activity with all the required fields, this call will error. See [Activity Action Field Requirements](#DOCS_GAME_SDK_ACTIVITIES/activity-action-field-requirements) for the fields required to have join and spectate invites function properly.
-
-Returns a `Discord.Result` via callback.
-
-###### Parameters
-
-| name | type | description |
-|---------|--------------------|-------------------------------------------------------|
-| userId | Int64 | the id of the user to invite |
-| type | ActivityActionType | marks the invite as an invitation to join or spectate |
-| content | string | a message to send along with the invite |
-
-###### Example
-
-```cs
-var userId = 53908232506183680;
-activityManager.SendInvite(userId, Discord.ActivityActionType.Join, "Come play!", (result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Success!");
- }
- else
- {
- Console.WriteLine("Failed");
- }
-});
-```
-
-## AcceptInvite
-
-Accepts a game invitation from a given userId.
-
-Returns a `Discord.Result` via callback.
-
-###### Parameters
-
-| name | type | description |
-|--------|-------|------------------------------------|
-| userId | Int64 | the id of the user who invited you |
-
-###### Example
-
-```cs
-activityManager.AcceptInvite(290926444748734466, (result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Success!");
- }
- else
- {
- Console.WriteLine("Failed");
- }
-});
-```
-
-## OnActivityJoin
-
-Fires when a user accepts a game chat invite or receives confirmation from Asking to Join.
-
-###### Parameters
-
-| name | type | description |
-|------------|--------|------------------------------------|
-| joinSecret | string | the secret to join the user's game |
-
-###### Example
-
-```cs
-// Received when someone accepts a request to join or invite.
-// Use secrets to receive back the information needed to add the user to the group/party/match
-activityManager.OnActivityJoin += secret => {
- Console.WriteLine("OnJoin {0}", secret);
- lobbyManager.ConnectLobbyWithActivitySecret(secret, (Discord.Result result, ref Discord.Lobby lobby) =>
- {
- Console.WriteLine("Connected to lobby: {0}", lobby.Id);
- // Connect to voice chat, used in this case to actually know in overlay if your successful in connecting.
- lobbyManager.ConnectVoice(lobby.Id, (Discord.Result voiceResult) => {
-
- if (voiceResult == Discord.Result.Ok)
- {
- Console.WriteLine("New User Connected to Voice! Say Hello! Result: {0}", voiceResult);
- }
- else
- {
- Console.WriteLine("Failed with Result: {0}", voiceResult);
- };
- });
- //Connect to given lobby with lobby Id
- lobbyManager.ConnectNetwork(lobby.Id);
- lobbyManager.OpenNetworkChannel(lobby.Id, 0, true);
- foreach (var user in lobbyManager.GetMemberUsers(lobby.Id))
- {
- //Send a hello message to everyone in the lobby
- lobbyManager.SendNetworkMessage(lobby.Id, user.Id, 0,
- Encoding.UTF8.GetBytes(String.Format("Hello, {0}!", user.Username)));
- }
- //Sends this off to a Activity callback named here as 'UpdateActivity' passing in the discord instance details and lobby details
- UpdateActivity(discord, lobby);
- });
-};
-
-void UpdateActivity(Discord.Discord discord, Discord.Lobby lobby)
- {
- //Creates a Static String for Spectate Secret.
- string discordSpectateSecret = "wdn3kvj320r8vk3";
- spectateActivitySecret = discordSpectateSecret;
- var activity = new Discord.Activity
- {
- State = "Playing Co-Op",
- Details = "In a Multiplayer Match!",
- Timestamps =
- {
- Start = startTimeStamp,
- },
- Assets =
- {
- LargeImage = "matchimage1",
- LargeText = "Inside the Arena!",
- },
- Party = {
- Id = lobby.Id.ToString(),
- Size = {
- CurrentSize = lobbyManager.MemberCount(lobby.Id),
- MaxSize = (int)lobby.Capacity,
- },
- },
- Secrets = {
- Spectate = spectateActivitySecret,
- Join = joinActivitySecret,
- },
- Instance = true,
- };
-
- activityManager.UpdateActivity(activity, result =>
- {
- Debug.LogFormat("Updated to Multiplayer Activity: {0}", result);
-
- // Send an invite to another user for this activity.
- // Receiver should see an invite in their DM.
- // Use a relationship user's ID for this.
- // activityManager
- // .SendInvite(
- // 364843917537050624,
- // Discord.ActivityActionType.Join,
- // "",
- // inviteResult =>
- // {
- // Console.WriteLine("Invite {0}", inviteResult);
- // }
- // );
- });
- }
-```
-
-## OnActivitySpectate
-
-Fires when a user accepts a spectate chat invite or clicks the Spectate button on a user's profile.
-
-###### Parameters
-
-| name | type | description |
-|----------------|--------|---------------------------------------------------|
-| spectateSecret | string | the secret to join the user's game as a spectator |
-
-###### Example
-
-```cs
-// Received when someone accepts a request to spectate
-activityManager.OnActivitySpectate += secret =>
-{
- Console.WriteLine("OnSpectate {0}", secret);
-};
-```
-
-## OnActivityJoinRequest
-
-Fires when a user asks to join the current user's game.
-
-###### Parameters
-
-| name | type | description |
-|------|------|-------------------------|
-| user | User | the user asking to join |
-
-###### Example
-
-```cs
-// A join request has been received. Render the request on the UI.
-activityManager.OnActivityJoinRequest += (ref Discord.User user) =>
-{
- Console.WriteLine("OnJoinRequest {0} {1}", user.Username, user.Id);
-};
-```
-
-## OnActivityInvite
-
-Fires when the user receives a join or spectate invite.
-
-###### Parameters
-
-| name | type | description |
-|----------|--------------------|--------------------------------------------|
-| type | ActivityActiontype | whether this invite is to join or spectate |
-| user | User | the user sending the invite |
-| activity | Activity | the inviting user's current activity |
-
-###### Example
-
-```cs
-// An invite has been received. Consider rendering the user / activity on the UI.
-activityManager.OnActivityInvite += (Discord.ActivityActionType Type, ref Discord.User user, ref Discord.Activity activity2) =>
-{
- Console.WriteLine("Received Invite Type: {0}, from User: {1}, with Activity Name: {2}", Type, user.Username, activity2.Name);
- // activityManager.AcceptInvite(user.Id, result =>
- // {
- // Console.WriteLine("AcceptInvite {0}", result);
- // });
-};
-```
-
-## Example: Inviting a User to a Game
-
-```cs
-var discord = new Discord.Discord(clientId, Discord.CreateFlags.Default);
-
-// Update user's activity for your game.
-// Party and secrets are vital.
-var activity = new Discord.Activity
-{
- State = "olleh",
- Details = "foo details",
- Timestamps =
- {
- Start = 5,
- End = 6,
- },
- Assets =
- {
- LargeImage = "foo largeImageKey",
- LargeText = "foo largeImageText",
- SmallImage = "foo smallImageKey",
- SmallText = "foo smallImageText",
- },
- Party =
- {
- Id = "foo partyID",
- Size = {
- CurrentSize = 1,
- MaxSize = 4,
- },
- },
- Secrets =
- {
- Match = "foo matchSecret",
- Join = "foo joinSecret",
- Spectate = "foo spectateSecret",
- },
- Instance = true,
-};
-
-activityManager.UpdateActivity(activity, (result) =>
-{
- Console.WriteLine("Update Activity {0}", result);
-
- // Send an invite to another user for this activity.
- // Receiver should see an invite in their DM.
- // Use a relationship user's ID for this.
- activityManager.SendInvite(364843917537050999, Discord.ActivityActionType.Join, "", (inviteUserResult) =>
- {
- Console.WriteLine("Invite User {0}", inviteUserResult);
- });
-});
-```
diff --git a/docs/game_sdk/Applications.md b/docs/game_sdk/Applications.md
deleted file mode 100644
index b827b25a1a..0000000000
--- a/docs/game_sdk/Applications.md
+++ /dev/null
@@ -1,240 +0,0 @@
-# Applications
-
-> info
-> Need help with the SDK? Talk to us in the [Discord Developers Server](https://discord.gg/discord-developers)!
-
-> warn
-> Selling SKUs on Discord has now been discontinued as of March 1, 2022. [Read here for more info.](https://support-dev.discord.com/hc/en-us/articles/6309018858647-Self-serve-Game-Selling-Deprecation)
-
-> danger
-> The GameSDK's Achievements, Applications, Voice, Images, Lobbies, Networking, Storage, and Store (purchases and discounts) features have been deprecated, and will be decommissioned on **May 2, 2023**. [Read more](#DOCS_CHANGE_LOG/gamesdk-feature-deprecation)
-
-Many games run their own backend servers for things like user authentication. If one of those many games is yours, then we've got something for you! This manager gives you access to a bearer token for the currently connected Discord user, which you can send off to your server to do user authentication.
-
-This token is also useful for retrieving information about the connected user's account. Check out our [OAuth2 documentation](https://discord.com/developers/docs/topics/oauth2) for more information.
-
-These bearer tokens are good for seven days, after which they will expire. When a user reconnects to your game, and is online and connected to the internet, they'll receive a new token that you can grab.
-
-This manager also includes a couple useful helper functions, like getting the locale in which the user has chosen to use their Discord client, and knowing which game branch the game is running on. More about branches in the Dispatch CLI tool section of the documentation.
-
-## Data Models
-
-###### OAuth2Token Struct
-
-| name | type | description |
-|-------------|--------|-------------------------------------------------------------------------------------------------|
-| AccessToken | string | a bearer token for the current user |
-| Scopes | string | a list of oauth2 scopes as a single string, delineated by spaces like `"identify rpc gdm.join"` |
-| Expires | Int64 | the timestamp at which the token expires |
-
-###### SignedAppTicket Struct
-
-| name | type | description |
-|----------------|--------------------------------------------------------------------------------------------------------------------------|----------------------------------------------------------|
-| application_id | Int64 | the application id for the ticket |
-| user | [User](#DOCS_GAME_SDK_USERS/data-models-user-struct) | the user for the ticket |
-| entitlements | list of partial [Entitlements](#DOCS_GAME_SDK_STORE/data-models-entitlement-struct) structs that contain just the SKU id | the list of the user's entitlements for this application |
-| timestamp | string | the ISO 8601 timestamp for the ticket |
-
-## GetCurrentLocale
-
-> info
-> Value from environment variable `DISCORD_CURRENT_LOCALE`
-
-Gets the locale the current user has Discord set to.
-
-Returns a `string`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var locale = applicationManager.GetCurrentLocale();
-Console.WriteLine("This user's language is {0}", locale);
-```
-
-## GetCurrentBranch
-
-> info
-> Value from environment variable `DISCORD_CURRENT_BRANCH`
-
-Get the name of pushed branch on which the game is running. These are branches that you created and pushed using Dispatch.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var branch = applicationManager.GetCurrentBranch();
-if (branch != MyBranches.Stable)
-{
- Console.WriteLine("You are on a beta branch; expect bugs!");
-}
-```
-
-## GetOAuth2Token
-
-> info
-> value from environment variable `DISCORD_ACCESS_TOKEN`
-
-> warn
-> Ensure that you have `http://127.0.0.1` set as a valid redirect URI for your application in the Developer Portal, or this method will always return an error.
-
-Retrieve an oauth2 bearer token for the current user. If your game was launched from Discord and you call this function, you will automatically receive the token. If the game was _not_ launched from Discord and this method is called, Discord will focus itself and prompt the user for authorization.
-
-Returns a `Discord.Result` and a `ref Discord.OAuth2Token` via callback.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-applicationManager.GetOAuth2Token((Discord.Result result, ref Discord.OAuth2Token token) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Token for the user: {0}. Expires in {1}", token.AccessToken, token.Expires);
- // You may now use this token against Discord's HTTP API
- }
-});
-```
-
-## ValidateOrExit
-
-Checks if the current user has the entitlement to run this game.
-
-Returns a `Discord.Result` via callback.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-applicationManager.ValidateOrExit((result) =>
-{
- if (result == Discord.Result.Ok)
- {
- // Game keeps running
- }
- else
- {
- Console.WriteLine("Oops! Something went wrong, closing game...");
- }
-});
-```
-
-## GetTicket
-
-###### Current Version
-
-| version | status |
-|---------|---------|
-| 2 | current |
-
-Get the signed app ticket for the current user. The structure of the ticket is: `version.signature.base64encodedjson`, so you should split the string by the `.` character. Ensure that the `version` matches the current version. The `signature` is used to verify the ticket using the libsodium library of your choice, and the `base64encodedjson` is what you can transform after verification. It contains:
-
-- the application id tied to the ticket
-- the user's user id
-- a timestamp for the ticket
-- the list of the user's [entitlements](#DOCS_GAME_SDK_STORE/data-models-entitlement-struct) for the application id
-
-These values can be accessed by transforming the string into a [SignedAppTicket](#DOCS_GAME_SDK_APPLICATIONS/data-models-signedappticket-struct) with your application's private key. The ticket is signed using [libsodium](https://github.com/jedisct1/libsodium) which should be available for any programming language. Here's a [list of available libraries](https://download.libsodium.org/doc/bindings_for_other_languages).
-
-Note that both the public key you receive from Discord and the signature within the app ticket from the SDK are both in hex, and will need to be converted to `byte[]` before use with libsodium.
-
-Returns a `Discord.Result` and `ref string` via callback.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-// Handle serialization however works best for you
-// This is just an easy example
-[Serializable]
-public class SignedAppTicket
-{
- public long application_id;
- public Discord.User user;
- public List entitlements;
- public string timestamp;
-}
-
-public void DoTheThing()
-{
- // This example is using the libsodium-net library
- // https://github.com/adamcaudill/libsodium-net
- var appManager = discord.GetApplicationManager();
- var MY_PUBLIC_KEY = "460cab5f2237b71e3c2c06bzze217f4f68d55db16dae672bdfb6618235589999";
- var MY_SKU_ID = "492432195219099999";
-
- // Get the ticket
- appManager.GetTicket((Discord.Result res, ref string ticket) =>
- {
- // Split the ticket into its parts
- var parts = ticket.Split('.');
-
- // Ensure the version matches
- if(parts[0] == "2")
- {
- // Verify the signature
- // Your public key will be given to you by Discord
- if (Sodium.PublicKeyAuth.VerifyDetached(HexToByte(parts[1]), System.Text.Encoding.UTF8.GetBytes(parts[2]), HexToByte(MY_PUBLIC_KEY)))
- {
- // If valid, decode the string
- var byteData = Convert.FromBase64String(parts[2]);
- var json = System.Text.Encoding.UTF8.GetString(byteData);
-
- // Deserialize it into the ticket object
- var myTicket = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
-
- // Check for entitlement to the SKU!
- if (myTicket.entitlements.Any(x => x.SkuId == MY_SKU_ID))
- {
- Console.WriteLine("User has entitlement to your game");
- }
- else
- {
- Console.WriteLine("Not entitled");
- }
- }
- }
- });
-}
-
-public byte[] HexToByte(string hex)
-{
- byte[] data = new byte[hex.Length / 2];
- for (int i = 0; i < hex.Length; i +=2)
- {
- data[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
- }
- return data;
-}
-```
-
-## Example: Get OAuth2 Token
-
-```cs
-var discord = new Discord.Discord(clientId, Discord.CreateFlags.Default);
-var appManager = discord.GetApplicationManager();
-
-// Retrieve the token
-appManager.GetOAuth2Token((Discord.Result result, ref Discord.OAuth2Token token) =>
-{
- Console.WriteLine(token.AccessToken);
-
- // Now send that token off to your server to do your own validation!
-})
-```
diff --git a/docs/game_sdk/Discord.md b/docs/game_sdk/Discord.md
deleted file mode 100644
index b182690d3f..0000000000
--- a/docs/game_sdk/Discord.md
+++ /dev/null
@@ -1,448 +0,0 @@
-# Discord
-
-> info
-> Need help with the SDK? Talk to us in the [Discord Developers Server](https://discord.gg/discord-developers)!
-
-> warn
-> Selling SKUs on Discord has now been discontinued as of March 1, 2022. [Read here for more info.](https://support-dev.discord.com/hc/en-us/articles/6309018858647-Self-serve-Game-Selling-Deprecation)
-
-> danger
-> The GameSDK's Achievements, Applications, Voice, Images, Lobbies, Networking, Storage, and Store (purchases and discounts) features have been deprecated, and will be decommissioned on **May 2, 2023**. [Read more](#DOCS_CHANGE_LOG/gamesdk-feature-deprecation)
-
-Making a game? Need a whole bunch of fancy APIs to help make it great and your players' lives a breeze? Look no further! The Discord GameSDK is an easy drop-in SDK to help you manage all the hard things that come with making a game. Well, all the hards things about coding it at least. Interpersonal communication skills are on you (have you heard of this cool chat app called Discord?).
-
-OK, cool, so how's it work?
-
-## General Structure
-
-At a high level, the Discord GameSDK has a class, `Discord`. This class is in charge of the creation of a few "manager" sub-classes. They are:
-
-- `ActivityManager` - for Rich Presence and game invites
-- `OverlayManager` - for interacting with Discord's built-in overlay
-- `RelationshipManager` - for users' social relationships across Discord, including friends list
-- `StoreManager` - for all things entitlements and SKUs, including IAP
-- `UserManager` - for fetching user data for a given id and the current user
-
-Deprecated managers:
-
-- `AchievementManager` - for achievements!
-- `ApplicationManager` - for retrieving a user's OAuth2 bearer token, locale, and current game branch
-- `ImageManager` - for getting data about images on Discord, like user avatars or chat images
-- `LobbyManager` - for multiplayer lobbies
-- `NetworkManager` - for all your networking layer needs
-- `StorageManager` - for saving game data to the disk and the cloud
-- `VoiceManager` - to make use of Discord's awesome voice chat
-
-Each one of these managers contain a number of methods and events used to interact with Discord in the context of the manager. For example, `RelationshipManager` has a function called `Filter()`, which lets you pare down a user's inter-Discord relationships based on a boolean condition, like being friends!
-
-## Functions in the SDK
-
-Most functions in the Discord GameSDK, uh, _function_ in a similar way. They take whatever parameters are required for the function to do its job—a user id, the requested size for an image, etc.—and a callback by means of a function pointer. That callback is fired when the function completes its work, letting you handle events without worrying about piping asynchronously-returned data to the right context.
-
-Some functions behave with a normal return behavior; e.g. `RelationshipManager.Count()` just returns the number directly. Don't worry, it's outlined in the docs.
-
-A quick example with our C# binding:
-
-```c#
-var userManager = discord.GetUserManager();
-
-// Return via callback
-userManager.GetUser(290926444748734465, (Discord.Result result, ref Discord.User otherUser) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine(otherUser.Username);
- Console.WriteLine(otherUser.Id);
- }
-});
-
-
-// Return normally
-userManager.OnCurrentUserUpdate += () =>
-{
- var currentUser = userManager.GetCurrentUser();
- Console.WriteLine(currentUser.Username);
- Console.WriteLine(currentUser.Discriminator);
- Console.WriteLine(currentUser.Id);
-};
-```
-
-## Environment Variables
-
-Discord passes a number of environment variables down to the SDK. These are accessed by various methods in the SDK and can be changed for local testing by changing the value in your local environment.
-
-###### SDK Environment Variables
-
-| name | method | description |
-|------------------------|---------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------|
-| DISCORD_INSTANCE_ID | [Local Testing](#DOCS_GAME_SDK_GETTING_STARTED/testing-locally-with-two-clients) | the locally running instance of Discord to connect to; allows you to choose between multiple running clients |
-| DISCORD_ACCESS_TOKEN | [ApplicationManager.GetOAuth2Token()](#DOCS_GAME_SDK_APPLICATIONS/getoauth2token) | the connected user's bearer token |
-| DISCORD_CURRENT_LOCALE | [ApplicationManager.GetCurrentLocale()](#DOCS_GAME_SDK_APPLICATIONS/getcurrentlocale) | the language that Discord is in for the connected user |
-| DISCORD_CURRENT_BRANCH | [ApplicationManager.GetCurrentBranch()](#DOCS_GAME_SDK_APPLICATIONS/getcurrentbranch) | the branch of the running application that the user has launched |
-| DISCORD_STORAGE_PATH | [StorageManager.GetPath()](#DOCS_GAME_SDK_STORAGE/getpath) | the path to which Discord will save files if you're using the StorageManager |
-
-## Error Handling
-
-Debugging is a pain, so before we get into the meat of the SDK, we want to make sure you're prepared for when things go awry. Within the Discord core is a function called `SetLogHook()`. It takes a `level`, which is minimum level of log message you want to listen to, and a callback function:
-
-```cs
-public void LogProblemsFunction(Discord.LogLevel level, string message)
-{
- Console.WriteLine("Discord:{0} - {1}", level, message);
-}
-
-discord.SetLogHook(Discord.LogLevel.Debug, LogProblemsFunction);
-```
-
-You should begin your integration by setting up this callback to help you debug. Helpfully, if you put a breakpoint inside the callback function you register here, you'll be able to see the stack trace for errors you run into (as long as they fail synchronously). Take the guess work out of debugging, or hey, ignore any and all logging by setting a callback that does nothing. We're not here to judge.
-
-## Data Models
-
-###### Result Enum
-
-| Code | value | description |
-|------|---------------------------------|-------------------------------------------------------------------------------------------------|
-| 0 | Ok | everything is good |
-| 1 | ServiceUnavailable | Discord isn't working |
-| 2 | InvalidVersion | the SDK version may be outdated |
-| 3 | LockFailed | an internal error on transactional operations |
-| 4 | InternalError | something on our side went wrong |
-| 5 | InvalidPayload | the data you sent didn't match what we expect |
-| 6 | InvalidCommand | that's not a thing you can do |
-| 7 | InvalidPermissions | you aren't authorized to do that |
-| 8 | NotFetched | couldn't fetch what you wanted |
-| 9 | NotFound | what you're looking for doesn't exist |
-| 10 | Conflict | user already has a network connection open on that channel |
-| 11 | InvalidSecret | activity secrets must be unique and not match party id |
-| 12 | InvalidJoinSecret | join request for that user does not exist |
-| 13 | NoEligibleActivity | you accidentally set an `ApplicationId` in your `UpdateActivity()` payload |
-| 14 | InvalidInvite | your game invite is no longer valid |
-| 15 | NotAuthenticated | the internal auth call failed for the user, and you can't do this |
-| 16 | InvalidAccessToken | the user's bearer token is invalid |
-| 17 | ApplicationMismatch | access token belongs to another application |
-| 18 | InvalidDataUrl | something internally went wrong fetching image data |
-| 19 | InvalidBase64 | not valid Base64 data |
-| 20 | NotFiltered | you're trying to access the list before creating a stable list with `Filter()` |
-| 21 | LobbyFull | the lobby is full |
-| 22 | InvalidLobbySecret | the secret you're using to connect is wrong |
-| 23 | InvalidFilename | file name is too long |
-| 24 | InvalidFileSize | file is too large |
-| 25 | InvalidEntitlement | the user does not have the right entitlement for this game |
-| 26 | NotInstalled | Discord is not installed |
-| 27 | NotRunning | Discord is not running |
-| 28 | InsufficientBuffer | insufficient buffer space when trying to write |
-| 29 | PurchaseCancelled | user cancelled the purchase flow |
-| 30 | InvalidGuild | Discord guild does not exist |
-| 31 | InvalidEvent | the event you're trying to subscribe to does not exist |
-| 32 | InvalidChannel | Discord channel does not exist |
-| 33 | InvalidOrigin | the origin header on the socket does not match what you've registered (you should not see this) |
-| 34 | RateLimited | you are calling that method too quickly |
-| 35 | OAuth2Error | the OAuth2 process failed at some point |
-| 36 | SelectChannelTimeout | the user took too long selecting a channel for an invite |
-| 37 | GetGuildTimeout | took too long trying to fetch the guild |
-| 38 | SelectVoiceForceRequired | push to talk is required for this channel |
-| 39 | CaptureShortcutAlreadyListening | that push to talk shortcut is already registered |
-| 40 | UnauthorizedForAchievement | your application cannot update this achievement |
-| 41 | InvalidGiftCode | the gift code is not valid |
-| 42 | PurchaseError | something went wrong during the purchase flow |
-| 43 | TransactionAborted | purchase flow aborted because the SDK is being torn down |
-
-###### LogLevel Enum
-
-| value | description |
-|---------|--------------------------------|
-| Error | Log only errors |
-| Warning | Log warnings and errors |
-| Info | Log info, warnings, and errors |
-| Debug | Log _all_ the things! |
-
-###### CreateFlags Enum
-
-| value | description |
-|------------------|---------------------------------------------------------------------|
-| Default | Requires Discord to be running to play the game |
-| NoRequireDiscord | Does not require Discord to be running, use this on other platforms |
-
-## Create
-
-Creates an instance of Discord to initialize the SDK. This is the overlord of all things Discord. We like to call her Nelly.
-
-Returns a new `Discord`.
-
-###### Parameters
-
-| name | type | description |
-|----------|-------------|-----------------------------------------------------|
-| clientId | Int64 | your application's client id |
-| flags | CreateFlags | the creation parameters for the SDK, outlined above |
-
-###### Example
-
-```cpp
-// c++ land
-discord::Core* core{};
-discord::Core::Create(53908232506183680, DiscordCreateFlags_Default, &core);
-
-// c# land
-var discord = new Discord(53908232506183680, (UInt64)Discord.CreateFlags.Default);
-```
-
-## Destroy
-
-Destroys the instance. Wave goodbye, Nelly! You monster. In C# land, this is `Dispose()`.
-
-> info
-> The C++ binding does not include a `destroy()` method, as the destructor for the Core does the work for you.
-
-Returns `void`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-discord.Dispose();
-```
-
-## SetLogHook
-
-Registers a logging callback function with the minimum level of message to receive. The callback function should have a signature of:
-
-```cs
-MyCallbackFunction(LogLevel level, string message);
-```
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|----------|----------|---------------------------------------------|
-| level | LogLevel | the minimum level of event to log |
-| callback | function | the callback function to catch the messages |
-
-###### Example
-
-```cs
-public void LogProblemsFunction(Discord.LogLevel level, string message)
-{
- Console.WriteLine("Discord:{0} - {1}", level, message);
-}
-
-discord.SetLogHook(Discord.LogLevel.Debug, LogProblemFunctions);
-```
-
-## RunCallbacks
-
-Runs all pending SDK callbacks. Put this in your game's main event loop, like `Update()` in Unity. That way, the first thing your game does is check for any new info from Discord.
-
-This function also serves as a way to know that the local Discord client is still connected. If the user closes Discord while playing your game, `RunCallbacks()` will return/throw `Discord.Result.NotRunning`.
-
-In C and C++, this function returns `Discord.Result`. In C#, it returns `void` and will throw `Discord.Result` error if something went wrong.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-void Update()
-{
- discord.RunCallbacks();
-}
-```
-
-## GetActivityManager
-
-Fetches an instance of the manager for interfacing with activities in the SDK.
-
-Returns an `ActivityManager`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var activityManager = discord.GetActivityManager();
-```
-
-## GetRelationshipManager
-
-Fetches an instance of the manager for interfacing with relationships in the SDK.
-
-Returns a `RelationshipManager`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var relationshipManager = discord.GetRelationshipManager();
-```
-
-## GetImageManager
-
-Fetches an instance of the manager for interfacing with images in the SDK.
-
-Returns an `ImageManager`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var imageManager = discord.GetImageManager();
-```
-
-## GetUserManager
-
-Fetches an instance of the manager for interfacing with users in the SDK.
-
-Returns an `UserManager`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var userManager = discord.GetUserManager();
-```
-
-## GetLobbyManager
-
-Fetches an instance of the manager for interfacing with lobbies in the SDK.
-
-Returns a `LobbyManager`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var lobbyManager = discord.GetLobbyManager();
-```
-
-## GetNetworkManager
-
-Fetches an instance of the manager for interfacing with networking in the SDK.
-
-Returns an `NetworkManager`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var networkManager = discord.GetNetworkManager();
-```
-
-## GetOverlayManager
-
-Fetches an instance of the manager for interfacing with the overlay in the SDK.
-
-Returns an `OverlayManager`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var overlayManager = discord.GetOverlayManager();
-```
-
-## GetApplicationManager
-
-Fetches an instance of the manager for interfacing with applications in the SDK.
-
-Returns an `ApplicationManager`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var applicationManager = discord.GetApplicationManager();
-```
-
-## GetStorageManager
-
-Fetches an instance of the manager for interfacing with storage in the SDK.
-
-Returns a `StorageManager`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var storageManager = discord.GetStorageManager();
-```
-
-## GetStoreManager
-
-Fetches an instance of the manager for interfacing with SKUs and Entitlements in the SDK.
-
-Returns a `StoreManager`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var storeManager = discord.GetStoreManager();
-```
-
-## GetVoiceManager
-
-Fetches an instance of the manager for interfacing with voice chat in the SDK.
-
-Returns a `VoiceManager`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var voiceManager = discord.GetVoiceManager();
-```
-
-## GetAchievementManager
-
-Fetches an instance of the manager for interfacing with achievements in the SDK.
-
-Returns an `AchievementManager`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var achievementManager = discord.GetAchievementManager();
-```
diff --git a/docs/game_sdk/Discord_Voice.md b/docs/game_sdk/Discord_Voice.md
deleted file mode 100644
index be6a5c7d21..0000000000
--- a/docs/game_sdk/Discord_Voice.md
+++ /dev/null
@@ -1,289 +0,0 @@
-# Voice
-
-> info
-> Need help with the SDK? Talk to us in the [Discord Developers Server](https://discord.gg/discord-developers)!
-
-> danger
-> The GameSDK's Achievements, Applications, Voice, Images, Lobbies, Networking, Storage, and Store (purchases and discounts) features have been deprecated, and will be decommissioned on **May 2, 2023**. [Read more](#DOCS_CHANGE_LOG/gamesdk-feature-deprecation)
-
-Discord's pride and joy is its voice chat. Well, ok, also its memes, but mostly the voice chat. Text and video chat are pretty great, too. And have you seen that store? Anyway.
-
-If you want people playing your game to be able to talk with each other, this Voice manager can help you out! Note that the main functionality for voice in this SDK is not _only_ in this manager. Connecting players to a voice chat happens with [ConnectVoice](#DOCS_GAME_SDK_LOBBIES/connectvoice) in the Lobby manager, and robust voice settings work through [OpenVoiceSettings](#DOCS_GAME_SDK_OVERLAY/openvoicesettings) in the Overlay manager. The Voice manager handles a few fine-grain details like self muting/deafening, swapping between VAD/PTT voice modes, and setting a PTT key. It's a subset of the robust settings from the overlay call for those of you that prefer to build UI and control things from your own game.
-
-## Data Models
-
-###### InputModeType Enum
-
-| name | value |
-|---------------|-------|
-| VoiceActivity | 0 |
-| PushToTalk | 1 |
-
-###### InputMode Struct
-
-| name | type | description |
-|----------|---------------|-----------------------------------------------|
-| Type | InputModeType | set either VAD or PTT as the voice input mode |
-| Shortcut | string | the PTT hotkey for the user |
-
-###### Shortcut Keys
-
-Keys can be mapped as a combination by adding a "+" between values, such as `"shift + 4"` or `"ctrl + v"`.
-
-| key type | value |
-|---------------|-----------------------------------------------------------|
-| Alphabetical | "a", "b", "c", etc. |
-| Numerical | "1", "2", "3", etc. |
-| Symbols | "-", "+", ".", "/", etc. |
-| Function Keys | "f1", "f2", "f3", etc. |
-| Gamepads | standard XInput api values - "GAMEPAD0", "GAMEPAD1", etc. |
-| Enter | "enter" |
-| Tab | "tab" |
-| Spacebar | "space" |
-| Backspace | "backspace" |
-| Escape | "esc" |
-| Meta | "meta" |
-| Shift | "shift" |
-| Caps Lock | "caps lock" |
-| Alt | "alt" |
-| Control | "ctrl" |
-| Right Shift | "right shift" |
-| Right Alt | "right alt" |
-| Right Control | "right ctrl" |
-| Right Meta | "right meta" |
-| Page Up | "page up" |
-| Page Down | "page down" |
-| Scroll Lock | "scroll lock" |
-| Print Screen | "print screen" |
-| Rewind | "rewind" |
-| Play | "play" |
-| Fast Forward | "fast forward" |
-| Delete | "del" |
-| End | "end" |
-| Insert | "insert" |
-| Break | "break" |
-| Home | "home" |
-| Up Arrow | "up" |
-| Down Arrow | "down" |
-| Left Arrow | "left" |
-| Right Arrow | "right" |
-
-## GetInputMode
-
-Get the current voice input mode for the user.
-
-Returns a `Discord.InputMode`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var voiceManager = discord.GetVoiceManager();
-var inputMode = voiceManager.GetInputMode();
-Console.WriteLine("The current input mode is {0}. The current PTT hotkey is set to {1}", inputMode.Type, inputMode.Shortcut);
-```
-
-## SetInputMode
-
-Sets a new voice input mode for the user. Refer to [Shortcut Keys](#DOCS_GAME_SDK_DISCORD_VOICE/data-models-shortcut-keys) for a table of valid values for shortcuts.
-
-Returns a `Discord.Result` via callback.
-
-###### Parameters
-
-| name | type | description |
-|-----------|-----------|---------------------------------|
-| inputMode | InputMode | the new input mode for the user |
-
-###### Example
-
-```cs
-var voiceManager = discord.GetVoiceManager();
-var newMode = new Discord.InputMode()
-{
- Type = Discord.InputModeType.PushToTalk,
- Shortcut = "ctrl"
-};
-voiceManager.SetInputMode(newMode, (res) =>
-{
- if (res == Discord.Result.Ok)
- {
- Console.WriteLine("New input mode set");
- }
-});
-```
-
-## IsSelfMute
-
-Whether the connected user is currently muted.
-
-Returns `bool`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var voiceManager = discord.GetVoiceManager();
-if (voiceManager.IsSelfMute())
-{
- Console.WriteLine("You are muted");
-}
-```
-
-## SetSelfMute
-
-Mutes or unmutes the currently connected user.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|------|------|---------------------------------|
-| mute | bool | true for mute, false for unmute |
-
-###### Example
-
-```cs
-var voiceManager = discord.GetVoiceManager();
-if (voiceManager.IsSelfMute())
-{
- voiceManager.SetSelfMute(false);
- Console.WriteLine("We automatically unmuted you");
-}
-```
-
-## IsSelfDeaf
-
-Whether the connected user is currently deafened.
-
-Returns `bool`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var voiceManager = discord.GetVoiceManager();
-if (voiceManager.IsSelfDeaf())
-{
- Console.WriteLine("You are deafened. You can't hear anyone!");
-}
-```
-
-## SetSelfDeaf
-
-Deafens or undeafens the currently connected user.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|------|------|---------------------------------|
-| deaf | bool | true for mute, false for unmute |
-
-###### Example
-
-```cs
-var voiceManager = discord.GetVoiceManager();
-if (voiceManager.IsSelfDeaf())
-{
- voiceManager.SetSelfDeaf(false);
- Console.WriteLine("We automatically undeafened you. You can hear now!");
-}
-```
-
-## IsLocalMute
-
-Whether the given user is currently muted by the connected user.
-
-Returns `bool`.
-
-###### Parameters
-
-| name | type | description |
-|--------|-------|-----------------------------|
-| userId | Int64 | the id of the user to check |
-
-###### Example
-
-```cs
-var voiceManager = discord.GetVoiceManager();
-if (voiceManager.IsLocalMute(53908232506183680))
-{
- Console.WriteLine("User is locally muted");
-}
-```
-
-## SetLocalMute
-
-Mutes or unmutes the given user for the currently connected user.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|--------|-------|---------------------------------|
-| userId | Int64 | the id of the user to mute |
-| mute | bool | true for mute, false for unmute |
-
-###### Example
-
-```cs
-var voiceManager = discord.GetVoiceManager();
-if (!voiceManager.IsLocalMute(53908232506183680))
-{
- voiceManager.SetLocalMute(53908232506183680, true);
- Console.WriteLine("Muted that user for you");
-}
-```
-
-## GetLocalVolume
-
-Gets the local volume for a given user. This is the volume level at which the currently connected users hears the given user speak.
-
-Returns `byte`.
-
-###### Parameters
-
-| name | type | description |
-|--------|-------|-----------------------------|
-| userId | Int64 | the id of the user to check |
-
-###### Example
-
-```cs
-var voiceManager = discord.GetVoiceManager();
-var volume = voiceManager.GetLocalVolume(53908232506183680);
-Console.WriteLine("User is at volume level {0}", volume);
-```
-
-## SetLocalVolume
-
-Sets the local volume for a given user. This is the volume level at which the currently connected users hears the given user speak. Valid volume values are from `0` to `200`, with `100` being the default. Lower than `100` will be a reduced volume level from default, whereas over `100` will be a boosted volume level from default.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|--------|-------|---------------------------------------------------|
-| userId | Int64 | the id of the user to change |
-| volume | byte | the volume at which to set the user, `0` to `200` |
-
-###### Example
-
-```cs
-var voiceManager = discord.GetVoiceManager();
-voiceManager.SetLocalVolume(53908232506183680, 70);
-```
diff --git a/docs/game_sdk/Getting_Started.md b/docs/game_sdk/Getting_Started.md
deleted file mode 100644
index d83497507e..0000000000
--- a/docs/game_sdk/Getting_Started.md
+++ /dev/null
@@ -1,307 +0,0 @@
-# Game SDK: Getting Started
-
-> info
-> Looking to build a game inside of Discord? Check out [Discord Activities](#DOCS_ACTIVITIES_OVERVIEW). We will be revisiting the Game SDK docs soon.
-
-> warn
-> Selling SKUs on Discord has now been discontinued as of March 1, 2022. [Read here for more info.](https://support-dev.discord.com/hc/en-us/articles/6309018858647-Self-serve-Game-Selling-Deprecation)
-
-> danger
-> The GameSDK's Achievements, Applications, Voice, Images, Lobbies, Networking, Storage, and Store (purchases and discounts) features have been deprecated, and will be decommissioned on **May 2, 2023**. [Read more](#DOCS_CHANGE_LOG/gamesdk-feature-deprecation)
-
-Welcome to the Discord GameSDK! We're glad you made it. This SDK is here to solve all your problems, if your problems include finding an awesome SDK to help develop your game. Our SDK is like Clippy, if Clippy were built on a modern tech stack, talked less, and was an awesome game development SDK.
-
-## Step 0 - Some Notes
-
-Before we get off to the races, a couple notes on the SDK:
-
-- All strings in the SDK are UTF8 strings
- - Make sure you've converted properly if necessary!
-- The SDK is **_NOT_** threadsafe!
- - Being callback-based, we thought that'd be confusing and inconsistent
-
-Now you know, and knowing is half the battle.
-
-## Step 1 - Get the Thing
-
-I know you're already convinced, so let's begin. First, get the SDK. Here it is:
-
-- [Discord GameSDK v3.2.1](https://dl-game-sdk.discordapp.net/3.2.1/discord_game_sdk.zip) - Latest version, includes Apple silicon (aarch64) support
-- [Discord GameSDK v2.5.6](https://dl-game-sdk.discordapp.net/2.5.6/discord_game_sdk.zip) - Try this version if you encounter bugs on the latest version
-
-There's a few things in there, but let's quickly talk about what the SDK actually _is_. Inside the `lib/` folder, you'll see `x86/` and `x86_64/` that have some `.lib`, `.bundle`, and `.dll` files. These are the things you want to distribute with your game.
-
-These files are comprised of two parts: a "stub", and fallback modules. What that means is that when everything is running smoothly, the DLLs will just call back to the local running Discord client to do the heavy lifting. If, however, something is wrong, like a breaking change, the files also include "fallback" modules that reflect the native SDK modules in Discord at the time that version of the SDK was published. TLDR - you don't need to worry about breaking changes.
-
-## Get Set Up
-
-Next, we need to set up the application for your game. An application is the base "entity" in Discord for your game; it's what all the builds, branches, SKUs, store pages, assets, etc. will be filed under.
-
-Head over to our [developer site](https://discord.com/developers/) and create an account/log in if you haven't yet. The first thing we're going to do is create a Team. Teams are groups of developers working together on applications; you should create a team for your organization at [https://discord.com/developers/teams](https://discord.com/developers/teams). You can invite other users to join your team and work on applications together with you.
-
-Now that your team is created, you'll want to make an application. To do so, click on "Applications" at the top of the page and create an application. Make sure you pick your newly-created team in the `Team` dropdown. You want your team to own the application; this unlocks store functionality! Now that your app is made, let's dive into some more setup.
-
-> warn
-> If you're integrating our SDK into an already-released game, there's a good chance that we may _already have_ an application in our database for your game! Reach out to our [Dev Support](https://dis.gd/devsupport) to learn more
-
-First, we'll need to set an OAuth2 redirect URL. You can add `http://127.0.0.1` in there for now; this powers some behind-the-scenes stuff you don't need to worry about.
-
-Next, copy the **Client ID** at the top of the page. This id, also referred to as an "application id", is your game's unique identifier across Discord. Keep it handy!
-
-While you're here, head to the "OAuth2" section of your application and add `http://127.0.0.1` as a redirect URI for your application. This will allow us to do the OAuth2 token exchange within the Discord client.
-
-Now we're gonna start coding. Didn't think we'd get there so fast, did ya? _Think again!_ The next sections are code primers for the main languages of the SDK: C#, C, and C++. They'll get you up and running with the most basic examples, and then you're off to the races.
-
-## Code Primer - Unity (Csharp)
-
-- Open up that SDK zip that you downloaded.
-- Copy the contents of the `lib/` folder to `Assets/Plugins` in your Unity project
-- Copy the contents of the `csharp/` folder to `Assets/Plugins/DiscordGameSDK`
-
-From there, you'll be able to reference functions in the DLL within your scripts. A basic example of a script can be found [in this example repo](https://github.com/msciotti/discord-game-sdk-test-apps/tree/master/cs-examples/unity-examples/Assets). In this example, we attach our `DiscordController.cs` script to the Main Camera object of the default created scene. We then instantiate the SDK with:
-
-```cs
-/*
- Grab that Client ID from earlier
- Discord.CreateFlags.Default will require Discord to be running for the game to work
- If Discord is not running, it will:
- 1. Close your game
- 2. Open Discord
- 3. Attempt to re-open your game
- Step 3 will fail when running directly from the Unity editor
- Therefore, always keep Discord running during tests, or use Discord.CreateFlags.NoRequireDiscord
-*/
-var discord = new Discord.Discord(CLIENT_ID, (UInt64)Discord.CreateFlags.Default);
-```
-
-You're now free to use other functionality in the SDK! Make sure to call `discord.RunCallbacks()` in your main game loop; that's your `Update()` function.
-
-You're ready to go! Check out the rest of the documentation for more info on how to use the other pieces of the SDK. See an example of everything it can do in `examples/Program.cs` in the SDK zip file.
-
-## Code Primer - Non-Unity Projects (Csharp)
-
-- Open up that SDK zip that you downloaded.
-- Create a folder in your project directory called `DiscordGameSDK` and copy the contents of the `csharp/` folder to it
-- Build your solution then place the `.dll` in the directory of the `.exe` (either x86 or x86_64 version depending on your compile platform). If you compile for Any CPU you may need to perform additional wrapping around DLL importing (like setting the DLL directory dynamically) to make sure you load the correct DLL.
-
-From there, you'll be able to reference functions in the DLL within your scripts. We then instantiate the SDK with:
-
-```cs
-/*
- Grab that Client ID from earlier
- Discord.CreateFlags.Default will require Discord to be running for the game to work
- If Discord is not running, it will:
- 1. Close your game
- 2. Open Discord
- 3. Attempt to re-open your game
- Step 3 may fail when running directly from your editor
- Therefore, always keep Discord running during tests, or use Discord.CreateFlags.NoRequireDiscord
-*/
-var discord = new Discord.Discord(CLIENT_ID, (UInt64)Discord.CreateFlags.Default);
-```
-
-You're now free to use other functionality in the SDK! Make sure to call `discord.RunCallbacks()` in your main game loop; that's your `Update()` function.
-
-You're ready to go! Check out the rest of the documentation for more info on how to use the other pieces of the SDK. See an example of everything it can do in `examples/Program.cs` in the SDK zip file.
-
-## Code Primer - Unreal Engine (C)
-
-Before jumping into the C binding, a word of caution. If you are using Unreal Engine 3, or need to support an older version of Visual Studio, you may at first see some unexpected crashes due to compile configurations. The way to fix this is to wrap the include statement for the Discord GameSDK header file like so:
-
-```c
-#pragma pack(push, 8)
-#include "discord_game_sdk.h"
-#pragma pack(pop)
-```
-
-This should let you use the SDK without any further crashes. Now, on with the show!
-
-- Open up that SDK zip that you downloaded.
-- Copy the contents of the `lib/` folder to the best location within your project for DLLs.
-- Copy the contents of the `c/` folder to your source directory
-- It's dangerous to go alone—take this small code block with you (to start)!
-
-```c
-struct Application {
- struct IDiscordCore* core;
- struct IDiscordUsers* users;
-};
-
-struct Application app;
-// Don't forget to memset or otherwise initialize your classes!
-memset(&app, 0, sizeof(app));
-
-struct IDiscordCoreEvents events;
-memset(&events, 0, sizeof(events));
-
-struct DiscordCreateParams params;
-params.client_id = CLIENT_ID;
-params.flags = DiscordCreateFlags_Default;
-params.events = &events;
-params.event_data = &app;
-
-DiscordCreate(DISCORD_VERSION, ¶ms, &app.core);
-```
-
-- Make sure to call `core->run_callbacks(core, 0)` in your game loop.
-
-You're ready to go! Check out the rest of the documentation for more info on how to use the other pieces of the SDK. See an example of everything it can do in `examples/c/main.c` in the SDK zip file.
-
-## Code Primer - Unreal Engine 4 (Cpp)
-
-Open up that SDK zip that you downloaded. There's a couple things in there that we care about. The first is the contents of the `cpp/` folder. These are our source files, including headers and `.cpp` file, that we'll need to reference in our build script. Second is the contents of the `lib/` folder. In this walkthrough we'll assume that we only care about win64, for ease of use.
-
-First, you'll want to copy the header files and `.cpp` files to a folder somewhere in your project directory. For ease of a quickstart example, you can put them right inside your `Source/your-project-name` folder; I'd put them in a containing folder called something like `discord-files/`.
-
-Second, you'll want to copy the `.dll` and `.lib` files from the `lib/x86_64` folder of the downloaded zip. These files should be put in `your-project-name/Binaries/Win64/`. For win32, take the files from `x86/` and put them, in `your-project-name/Binaries/Win32`.
-
-Next, we need to link these files within our project so that we can reference them. If you open up your project's `.sln` file in Visual Studio, you'll find a file called `your-project-name.Build.cs`. We're going to add the following lines of code to that file:
-
-```cpp
-/*
- ABSOLUTE_PATH_TO_DISCORD_FILES_DIRECTORY will look something like:
-
- "H:\\Unreal Projects\\gamesdktest\\Source\\gamesdktest\\discord-files\\"
-
- You should get this value programmatically
-*/
-PublicIncludePaths.Add(ABSOLUTE_PATH_TO_DISCORD_FILES_DIRECTORY)
-
-/*
- ABSOLUTE_PATH_TO_LIB_FILE will look something like:
-
- "H:\\Unreal Projects\\gamesdktest\\Binaries\\Win64\\discord_game_sdk.dll.lib"
-
- You should get this value programmatically
-*/
-PublicAdditionalLibraries.Add(ABSOLUTE_PATH_TO_LIB_FILE)
-```
-
-Now that we've got our new dependencies properly linked, we can reference them in our code. In this example, we're going to make a new `Pawn` class called `MyPawn`. It will look something like this:
-
-```cpp
-#include "MyPawn.h"
-#include "discord-files/discord.h"
-
-discord::Core* core{};
-
-AMyPawn::AMyPawn()
-{
- // Set this pawn to call Tick() every frame. You can turn this off to improve performance if you don't need it.
- PrimaryActorTick.bCanEverTick = true;
-}
-
-// Called when the game starts or when spawned
-void AMyPawn::BeginPlay()
-{
- Super::BeginPlay();
- /*
- Grab that Client ID from earlier
- Discord.CreateFlags.Default will require Discord to be running for the game to work
- If Discord is not running, it will:
- 1. Close your game
- 2. Open Discord
- 3. Attempt to re-open your game
- Step 3 will fail when running directly from the Unreal Engine editor
- Therefore, always keep Discord running during tests, or use Discord.CreateFlags.NoRequireDiscord
- */
- auto result = discord::Core::Create(461618159171141643, DiscordCreateFlags_Default, &core);
- discord::Activity activity{};
- activity.SetState("Testing");
- activity.SetDetails("Fruit Loops");
- core->ActivityManager().UpdateActivity(activity, [](discord::Result result) {
-
- });
-}
-
-// Called every frame
-void AMyPawn::Tick(float DeltaTime)
-{
- Super::Tick(DeltaTime);
- ::core->RunCallbacks();
-}
-
-// Called to bind functionality to input
-void AMyPawn::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
-{
- Super::SetupPlayerInputComponent(PlayerInputComponent);
-}
-```
-
-Make sure you've got `core->RunCallbacks()` going every frame!
-
-You're ready to go! Check out the rest of the documentation for more info on how to use the other pieces of the SDK. See an example of everything it can do in `examples/cpp/main.cpp` in the SDK zip file.
-
-## Code Primer - No Engine (Cpp)
-
-In your project folder, you'll want to make something like a "discord-files" folder, for organization. In that folder, copy all the `.h` and `.cpp` files from the zip.
-You want to include all the header and source files respectively in your project
-
-
-
-In your project settings, you'll want to include the relevant library (e.g. `discord_game_sdk.dll.lib`) as an additional dependency.
-
-
-
-- From there, you should be able to `#include "discord-files/discord.h"`, or whatever the path to that header file is, and have access to the code.
-
-## Testing Locally with Two Clients
-
-> info
-> Value from environment variable `DISCORD_INSTANCE_ID`
-
-While integrating the Discord GameSDK, you will probably find yourself wanting to test functionality between two game clients locally, be it for networking, Rich Presence, etc.
-
-We also know that getting a test build of a game on two separate machines can be both difficult and cumbersome. So, we've got a solution for you! By using system environment variables, you can tell the SDK in a certain game client to connect to a specific Discord client. Here's how it works:
-
-1. Download Discord Canary. This is our most updated build, and is good to develop against: [Windows](https://discord.com/api/download/canary?platform=win) - [Mac](https://discord.com/api/download/canary?platform=osx)
-2. Download a second Discord Build. Here's our Public Test Build: [Windows](https://discord.com/api/download/ptb?platform=win) - [Mac](https://discord.com/api/download/ptb?platform=osx)
-3. Open up two Discord clients. We recommend you develop against Discord Canary, so you can use PTB or Stable for your test account
-4. Log in with two separate users. Make sure any test account is added to the application's App Whitelist in the portal!
-
-Now, in your game code, you can tell the SDK which client to connect to via the environment variable `DISCORD_INSTANCE_ID` **before initializing the SDK**. The value of the variable corresponds to the order in which you opened the clients, so `0` would connect to the first opened client, `1` the second, etc.
-
-###### Environment Variable Example
-
-```cs
-// This machine opened Discord Canary first, and Discord PTB second
-
-// This makes the SDK connect to Canary
-System.Environment.SetEnvironmentVariable("DISCORD_INSTANCE_ID", "0");
-var discord = new Discord(applicationId, Discord.CreateFlags.Default);
-
-// This makes the SDK connect to PTB
-System.Environment.SetEnvironmentVariable("DISCORD_INSTANCE_ID", "1");
-var discord = new Discord(applicationId, Discord.CreateFlags.Default);
-```
-
-This will set the environment variable only within the context of the running process, so don't worry about messing up global stuff.
-
-> danger
-> If you test with this, make sure to remove this code before pushing a production build. It will interfere with the way that Discord launches games for users.
-
-## Section Checklist
-
-Think of these like those end of section review pages from your history textbooks, but we won't give you a pop quiz. I promise. By now, you should have the following:
-
-- The SDK downloaded
-- An application created, and a Client ID you're keeping handy
-- Rich Presence enabled on that application
-- An OAuth2 redirect URL added to that application
-- The proper libraries, DLLs, and header files in the right places for your game
-- A working SDK, via the small code snippets above
-
-If you can check all those boxes, you are doing great! You're well-equipped to venture forth into the rest of the SDK and make full use of it's myriad of functionality. So, onwards, to game development!
-
-If you ever need help during the process, you can always reach out to us at our [Dev Support](https://dis.gd/devsupport) or talk to us in the [Discord Developers Server](https://discord.gg/discord-developers)!
-
-## Where...do I go...
-
-Oh, yeah. Pseudo Table of Contents:
-
-- [The Core - Start Here!](#DOCS_GAME_SDK_DISCORD/)
-- [Activities, a.k.a. Rich Presence](#DOCS_GAME_SDK_ACTIVITIES/)
-- [Relationships](#DOCS_GAME_SDK_RELATIONSHIPS/)
-- [Users](#DOCS_GAME_SDK_USERS/)
-- [Overlay](#DOCS_GAME_SDK_OVERLAY/)
-- [Store](#DOCS_GAME_SDK_STORE/)
diff --git a/docs/game_sdk/Images.md b/docs/game_sdk/Images.md
deleted file mode 100644
index 7632956e1c..0000000000
--- a/docs/game_sdk/Images.md
+++ /dev/null
@@ -1,196 +0,0 @@
-# Images
-
-> info
-> Need help with the SDK? Talk to us in the [Discord Developers Server](https://discord.gg/discord-developers)!
-
-> danger
-> The GameSDK's Achievements, Applications, Voice, Images, Lobbies, Networking, Storage, and Store (purchases and discounts) features have been deprecated, and will be decommissioned on **May 2, 2023**. [Read more](#DOCS_CHANGE_LOG/gamesdk-feature-deprecation)
-
-Discord is like a book; it's better with pictures. The image manager helps you fetch image data for images in Discord, including user's avatars. They worked hard to pick out those photos and gifs. Show them you care, too.
-
-## Data Models
-
-###### ImageDimensions Struct
-
-| name | type | description |
-|--------|--------|-------------------------|
-| Width | UInt32 | the width of the image |
-| Height | UInt32 | the height of the image |
-
-###### ImageType Enum
-
-| value | description |
-|-------|--------------------------|
-| User | image is a user's avatar |
-
-###### ImageHandle Struct
-
-| name | type | description |
-|------|-----------|-------------------------------------------------|
-| Type | ImageType | the source of the image |
-| Id | Int64 | the id of the user whose avatar you want to get |
-| Size | UInt32 | the resolution at which you want the image |
-
-## Fetch
-
-Prepares an image to later retrieve data about it.
-
-Returns a `Discord.Result` and `Discord.ImageHandle` via callback.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------------|-------------------------------------------------------------|
-| handle | ImageHandle | contains the desired userId and size for the returned image |
-| refresh | bool | whether to use cached data for fetch anew |
-
-###### Example
-
-```cs
-var handle = new Discord.ImageHandle()
-{
- Id = 53908232506183680,
- Size = 1024
-};
-
-imageManager.Fetch(handle, false, (result, returnedHandle) =>
-{
- if (result == Discord.Result.Ok)
- {
- var data = imageManager.GetData(returnedHandle);
- // Do stuff with the byte[] data
- }
-});
-```
-
-## GetDimensions
-
-Gets the dimensions for the given user's avatar's source image.
-
-Returns `Discord.ImageDimensions`.
-
-###### Parameters
-
-| name | type | description |
-|--------|-------------|-------------------------------------------------------------|
-| handle | ImageHandle | contains the desired userId and size for the returned image |
-
-###### Example
-
-```cs
-var handle = new Discord.ImageHandle()
-{
- Id = 53908232506183680,
- Size = 1024
-};
-var dimensions = imageManager.GetDimensions(handle);
-```
-
-## GetData
-
-Gets the image data for a given user's avatar. In C#, this is overloaded by a helper function that will directly return a `byte[]` with the image data in it. In C++/C, this function reads image data into a passed pointer of defined size.
-
-###### Parameters
-
-| name | type | description |
-|--------|-------------|-----------------------------------------------|
-| handle | ImageHandle | the image handle from the `Fetch()` callback |
-| data | uint8_t\* | a buffer to read image data into (C++/C only) |
-| size | uint | the size of the buffer (C++/C only) |
-
-###### Example
-
-```cs
-var handle = new Discord.ImageHandle()
-{
- Id = 53908232506183680,
- Size = 1024
-};
-
-imageManager.Fetch(handle, false, (result, handle) =>
-{
- if (result == Discord.Result.Ok)
- {
- var data = imageManager.GetData(handle);
- // Do stuff with data now
- }
-});
-```
-
-###### Example Cpp
-
-```cpp
-core->ImageManager().Fetch(
- handle, true, [&state](discord::Result res, discord::ImageHandle handle) {
- if (res == discord::Result::Ok) {
- discord::ImageDimensions dims{};
- state.core->ImageManager().GetDimensions(handle, &dims);
- std::cout << "Fetched " << dims.GetWidth() << "x" << dims.GetHeight()
- << " avatar!\n";
-
- std::vector data;
- data.reserve(dims.GetWidth() * dims.GetHeight() * 4);
- uint8_t* d = data.data();
- state.core->ImageManager().GetData(handle, d, data.size());
- }
- }
-);
-```
-
-## GetTexture
-
-> warn
-> This is only exposed in Unity
-
-Gets the `Texture2D` for a given user's avatar for use within a Unity environment.
-
-Returns a `Texture2D`.
-
-###### Parameters
-
-| name | type | description |
-|--------|-------------|----------------------------------------------|
-| handle | ImageHandle | the image handle from the `Fetch()` callback |
-
-###### Example
-
-```cs
-var handle = new Discord.ImageHandle()
-{
- Id = 53908232506183680,
- Size = 1024
-};
-
-imageManager.Fetch(handle, false, (result, handle) =>
-{
- if (result == Discord.Result.Ok)
- {
- var texture = imageManager.GetTexture(handle);
- // Do stuff with texture now
- }
-});
-```
-
-## Example: User's Avatar Data
-
-```cs
-var discord = new Discord.Discord(clientId, Discord.CreateFlags.Default);
-
-// Request user's avatar data. Sizes can be powers of 2 between 16 and 2048
-imageManager.Fetch(Discord.ImageHandle.User(53908232506183680, 128), (result, handle) =>
-{
- {
- if (result == Discord.Result.Ok)
- {
- // If you are working in Unity, you can also use GetTexture()
- // Which is only exposed for Unity builds
- // These return raw RGBA.
- var data = imageManager.GetData(handle);
- }
- else
- {
- Console.WriteLine("image error {0}", handle.Id);
- }
- }
-};
-```
diff --git a/docs/game_sdk/Lobbies.md b/docs/game_sdk/Lobbies.md
deleted file mode 100644
index 0ba230fd8b..0000000000
--- a/docs/game_sdk/Lobbies.md
+++ /dev/null
@@ -1,1627 +0,0 @@
-# Lobbies
-
-> info
-> Need help with the SDK? Talk to us in the [Discord Developers Server](https://discord.gg/discord-developers)!
-
-> danger
-> The GameSDK's Achievements, Applications, Voice, Images, Lobbies, Networking, Storage, and Store (purchases and discounts) features have been deprecated, and will be decommissioned on **May 2, 2023**. [Read more](#DOCS_CHANGE_LOG/gamesdk-feature-deprecation)
-
-Looking to integrate multiplayer into your game? Lobbies are a great way to organize players into contexts to play together. This manager works hand in hand with the networking layer of our SDK to make multiplayer integrations a breeze by:
-
-- Creating, managing, and joining lobbies
-- Matchmaking users based on lobby metadata, like ELO
-- Getting and setting arbitrary metadata on lobbies and lobby members
-
-Lobbies in Discord work in one of two ways. By using calls from the SDK, lobbies are effectively "owned" by the user who's client creates the lobby. Someone boots up the game, hits your "Create Lobby" button, and their game client calls `LobbyManager.CreateLobby()` from the Discord SDK.
-
-There is also another way to create and "own" lobbies with which the source of truth can be your own server. These SDK functions calls map to API endpoints that are exposed in Discord's HTTP API. In lieu of creating and managing lobbies in the SDK, you can call those endpoints directly with a token for your application and take care of it all on some far-away, totally secure server. Let's go over the SDK first.
-
-## The SDK Way
-
-In order to ensure that Discord lobbies are consistent for all players, this manager works with "transactions". A `LobbyTransaction` is needed to set lobby properties, like capacity. A `MemberTransaction` is needed to set lobby member properties, like metadata.
-
-To update a user or a lobby, create or get a transaction for that resource, call the needed methods on it, and then pass it to the `Create()` or `Update()` methods. When passed to a `Create()` or `Update()` method, the transaction objected is consumed. So, if you want to do another `Create()` or `Update()`, you need to get a new transaction.
-
-###### Example: Creating a Lobby
-
-```cs
-var lobbyManager = discord.GetLobbyManager();
-
-// Create the transaction
-var txn = lobbyManager.GetLobbyCreateTransaction();
-
-// Set lobby information
-txn.SetCapacity(6);
-txn.SetType(Discord.LobbyType.Public);
-txn.SetMetadata("a", "123");
-
-// Create it!
-lobbyManager.CreateLobby(txn, (Discord.Result result, ref Discord.Lobby lobby) =>
-{
- Console.WriteLine("lobby {0} created with secret {1}", lobby.Id, lobby.Secret);
-
- // We want to update the capacity of the lobby
- // So we get a new transaction for the lobby
- var newTxn = lobbyManager.GetLobbyUpdateTransaction(lobby.id);
- newTxn.SetCapacity(5);
-
- lobbyManager.UpdateLobby(lobby.id, newTxn, (result) =>
- {
- Console.WriteLine("lobby {0} updated", lobby.Id);
- });
-});
-```
-
-## Data Models
-
-###### LobbyType Enum
-
-| name | value |
-|---------|-------|
-| Private | 1 |
-| Public | 2 |
-
-###### Lobby Struct
-
-| name | type | description |
-|----------|-----------|----------------------------------------|
-| Id | Int64 | the unique id of the lobby |
-| Type | LobbyType | if the lobby is public or private |
-| OwnerId | Int64 | the userId of the lobby owner |
-| Secret | string | the password to the lobby |
-| Capacity | UInt32 | the max capacity of the lobby |
-| Locked | bool | whether or not the lobby can be joined |
-
-###### LobbySearchComparison Enum
-
-| name | value |
-|--------------------|-------|
-| LessThanOrEqual | -2 |
-| LessThan | -1 |
-| Equal | 0 |
-| GreaterThan | 1 |
-| GreaterThanOrEqual | 2 |
-| NotEqual | 3 |
-
-###### LobbySearchCast Enum
-
-| name | value |
-|--------|-------|
-| String | 1 |
-| Number | 2 |
-
-###### LobbySearchDistance Enum
-
-| name | value | description |
-|----------|-------|--------------------------------------|
-| Local | 0 | within the same region |
-| Default | 1 | within the same and adjacent regions |
-| Extended | 2 | far distances, like US to EU |
-| Global | 3 | all regions |
-
-###### LobbyTransaction Struct
-
-Has no values, but has member functions, outlined later.
-
-###### LobbyMemberTransaction Struct
-
-Has no values, but has member functions, outlined later.
-
-###### LobbySearchQuery Struct
-
-Has no values, but has member functions, outlined later.
-
-## LobbyTransaction.SetType
-
-Marks a lobby as private or public.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|------|-----------|-------------------|
-| type | LobbyType | private or public |
-
-###### Example
-
-```cs
-var txn = lobbyManager.GetLobbyUpdateTransaction();
-txn.SetType(Discord.LobbyType.Public);
-lobbyManager.UpdateLobby(lobbyId, txn, (Discord.Result result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Lobby type updated!");
- }
-});
-```
-
-## LobbyTransaction.SetOwner
-
-> warn
-> This method is only valid for `LobbyUpdateTransactions` and may cause issues if you set it on a `LobbyCreateTransaction`.
-
-Sets a new owner for the lobby.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|--------|-------|-------------------------|
-| userId | Int64 | the new owner's user id |
-
-###### Example
-
-```cs
-var txn = lobbyManager.GetLobbyUpdateTransaction();
-txn.SetOwner(53908232506183680);
-lobbyManager.UpdateLobby(lobbyId, txn, (Discord.Result result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Lobby owner updated!");
- }
-});
-```
-
-## LobbyTransaction.SetCapacity
-
-Sets a new capacity for the lobby.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|----------|--------|------------------------|
-| capacity | UInt32 | the new max lobby size |
-
-###### Example
-
-```cs
-var txn = lobbyManager.GetLobbyUpdateTransaction();
-txn.SetCapacity(10);
-lobbyManager.UpdateLobby(lobbyId, txn, (Discord.Result result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Lobby capacity updated!");
- }
-});
-```
-
-## LobbyTransaction.SetMetadata
-
-Sets metadata value under a given key name for the lobby.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|-------|--------|------------------|
-| key | string | key for the data |
-| value | string | data value |
-
-###### Example
-
-```cs
-var txn = lobbyManager.GetLobbyUpdateTransaction();
-txn.SetMetadata("average_mmr", "4500");
-lobbyManager.UpdateLobby(lobbyId, txn, (Discord.Result result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Lobby metadata updated!");
- }
-});
-```
-
-## LobbyTransaction.DeleteMetadata
-
-Deletes the lobby metadata for a key.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|------|--------|------------------|
-| key | string | key for the data |
-
-###### Example
-
-```cs
-var txn = lobbyManager.GetLobbyUpdateTransaction();
-txn.DeleteMetadata("average_mmr");
-lobbyManager.UpdateLobby(lobbyId, txn, (Discord.Result result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Lobby metadata updated!");
- }
-});
-```
-
-## LobbyTransaction.SetLocked
-
-Sets the lobby to locked or unlocked. When locked, new users cannot join the lobby.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|--------|------|-------------------------------------|
-| locked | bool | whether to lock or unlock the lobby |
-
-###### Example
-
-```cs
-var txn = lobbyManager.GetLobbyUpdateTransaction();
-txn.SetLocked(true);
-lobbyManager.UpdateLobby(lobbyId, txn, (Discord.Result result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Lobby type updated!");
- }
-});
-```
-
-## LobbyMemberTransaction.SetMetadata
-
-Sets metadata value under a given key name for the current user.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|-------|--------|------------------|
-| key | string | key for the data |
-| value | string | data value |
-
-###### Example
-
-```cs
-var txn = lobbyManager.GetMemberUpdateTransaction();
-txn.SetMetadata("current_mmr", "4267");
-lobbyManager.UpdateMember(lobbyId, memberId, txn, (result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Member metadata updated!");
- }
-});
-```
-
-## LobbyMemberTransaction.DeleteMetadata
-
-Sets metadata value under a given key name for the current user.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|------|--------|------------------|
-| key | string | key for the data |
-
-###### Example
-
-```cs
-var txn = lobbyManager.GetMemberUpdateTransaction();
-txn.DeleteMetadata("current_mmr");
-lobbyManager.UpdateMember(lobbyId, memberId, txn, (result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Member metadata updated!");
- }
-});
-```
-
-## LobbySearchQuery.Filter
-
-Filters lobbies based on metadata comparison. Available filter values are `owner_id`, `capacity`, `slots`, and `metadata`. If you are filtering based on metadata, make sure you prepend your key with `"metadata."` For example, filtering on matchmaking rating would be `"metadata.matchmaking_rating"`.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|-------|-----------------------|----------------------------------------------------------------------------|
-| key | string | key to search for filter data |
-| comp | LobbySearchComparison | how the value on the lobby metadata should be compared to the search value |
-| cast | LobbySearchCast | should the search value be cast as a string or a number |
-| value | string | the value to filter against |
-
-###### Example
-
-```cs
-var query = lobbyManager.GetSearchQuery();
-query.Filter("metadata.matchmaking_rating", LobbySearchComparison.GreaterThan, LobbySearchCast.Number, "455");
-```
-
-## LobbySearchQuery.Sort
-
-Sorts the filtered lobbies based on "near-ness" to a given value.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|-------|-----------------|---------------------------------------------------------|
-| key | string | key for the data |
-| cast | LobbySearchCast | should the search value be cast as a string or a number |
-| value | string | the value to sort by |
-
-###### Example
-
-```cs
-var query = lobbyManager.GetSearchQuery();
-query.Sort("metadata.ELO", LobbySearchCast.Number, "1337");
-```
-
-## LobbySearchQuery.Limit
-
-Limits the number of lobbies returned in a search.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|-------|--------|----------------------------------------|
-| limit | UInt32 | the number of lobbies to return at max |
-
-###### Example
-
-```cs
-var query = lobbyManager.GetSearchQuery();
-query.Limit(10);
-```
-
-## LobbySearchQuery.Distance
-
-Filters lobby results to within certain regions relative to the user's location.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|----------|-----------------------------|-------------------------------------------------|
-| distance | Discord.LobbySearchDistance | the distance within which to search for lobbies |
-
-###### Example
-
-```cs
-var query = lobbyManager.GetSearchQuery();
-query.Distance(LobbySearchDistance.Local);
-```
-
-## GetLobbyCreateTransaction
-
-Gets a Lobby transaction used for creating a new lobby
-
-Returns a `Discord.LobbyTransaction`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var txn = lobbyManager.GetLobbyCreateTransaction();
-```
-
-## GetLobbyUpdateTransaction
-
-Gets a lobby transaction used for updating an existing lobby.
-
-Returns a `Discord.LobbyTransaction`.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|------------------------------|
-| lobbyId | Int64 | the lobby you want to change |
-
-###### Example
-
-```cs
-var txn = lobbyManager.GetLobbyUpdateTransaction(290926798626357250);
-```
-
-## GetMemberUpdateTransaction
-
-Gets a new member transaction for a lobby member in a given lobby.
-
-Returns a `Discord.LobbyMemberTransaction`.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|------------------------------|
-| lobbyId | Int64 | the lobby you want to change |
-| userId | Int64 | the user you wish to change |
-
-###### Example
-
-```cs
-var txn = lobbyManager.GetMemberUpdateTransaction(290926798626357250, 53908232506183680);
-```
-
-## CreateLobby
-
-Creates a lobby. Creating a lobby auto-joins the connected user to it. **Do not call `SetOwner()` in the transaction for this method.**
-
-Returns `Discord.Result` and `ref Discord.Lobby` via callback.
-
-###### Parameters
-
-| name | type | description |
-|-------------|------------------|-------------------------------------------------------|
-| transaction | LobbyTransaction | a lobby transaction with set properties like capacity |
-
-###### Example
-
-```cs
-lobbyManager.CreateLobby(txn, (Discord.Result result, ref Discord.Lobby lobby) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Created lobby {0}", lobby.Id);
- }
-});
-```
-
-## UpdateLobby
-
-Updates a lobby with data from the given transaction. You _can_ call `SetOwner()` in this transaction.
-
-Returns `Discord.Result` via callback.
-
-> warn
-> This call has a rate limit of 10 updates per 5 seconds. If you fear you might hit that, it may be a good idea to batch your lobby updates into transactions.
-
-###### Parameters
-
-| name | type | description |
-|-------------|------------------|-------------------------------------|
-| lobbyId | Int64 | the lobby you want to change |
-| transaction | LobbyTransaction | the transaction with wanted changes |
-
-###### Example
-
-```cs
-lobbymanager.UpdateLobby(290926798626357250, transaction, (result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Lobby updated!");
- }
-});
-```
-
-## DeleteLobby
-
-Deletes a given lobby.
-
-Returns `Discord.Result` via callback.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|------------------------------|
-| lobbyId | Int64 | the lobby you want to delete |
-
-###### Example
-
-```cs
-lobbyManager.DeleteLobby(290926798626357250, (result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Lobby deleted!");
- }
-});
-```
-
-## ConnectLobby
-
-Connects the current user to a given lobby. You can be connected to up to five lobbies at a time.
-
-Returns `Discord.Result` and `ref Discord.Lobby` via callback.
-
-###### Parameters
-
-| name | type | description |
-|-------------|--------|----------------------------------|
-| lobbyId | Int64 | the lobby you want to connect to |
-| lobbySecret | string | the password for the lobby |
-
-###### Example
-
-```cs
-lobbyManager.ConnectLobby(290926798626357250, "363446008341987328:123123", (Discord.Result result, ref Discord.Lobby lobby) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Connected to lobby {0}!", lobby.Id);
- }
-});
-```
-
-## ConnectLobbyWithActivitySecret
-
-Connects the current user to a lobby; requires the special activity secret from the lobby which is a concatenated lobbyId and secret.
-
-Returns `Discord.Result` and `ref Discord.Lobby` via callback.
-
-###### Parameters
-
-| name | type | description |
-|----------------|--------|-------------------------------------------|
-| activitySecret | string | the special activity secret for the lobby |
-
-###### Example
-
-```cs
-lobbyManager.ConnectLobbyWithActivitySecret("363446008341987328:123123", (Discord.Result result, ref Discord.Lobby lobby) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Connected to lobby {0}!", lobby.Id);
- }
-});
-```
-
-## GetLobbyActivitySecret
-
-Gets the special activity secret for a given lobby. If you are creating lobbies from game clients, use this to easily interact with Rich Presence invites. Set the returned secret to your activity's `JoinSecret`.
-
-Returns `string`.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|------------------------------------------|
-| lobbyId | Int64 | the lobby you want to get the secret for |
-
-###### Example
-
-```cs
-var activitySecret = lobbyManager.GetLobbyActivitySecret(290926798626357250);
-var activity = new Discord.Activity
-{
- State = "olleh",
- Details = "foo details",
- Party = {
- Id = "foo partyID",
- Size = {
- CurrentSize = 1,
- MaxSize = 4,
- },
- },
- Secrets = {
- Join = activitySecret,
- },
- Instance = true,
-};
-
-ActivityManager.UpdateActivity(activity, (result) =>
-{
- Console.WriteLine("Update Activity {0}", result);
-});
-```
-
-## DisconnectLobby
-
-Disconnects the current user from a lobby.
-
-Returns `Discord.Result` via callback.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|-----------------------------|
-| lobbyId | Int64 | the lobby you want to leave |
-
-###### Example
-
-```cs
-lobbyManager.DisconnectLobby(290926798626357250, (result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Left lobby!");
- }
-});
-```
-
-## GetLobby
-
-Gets the lobby object for a given lobby id. Because of the way that the SDK is architected, you must first call [`Search()`](#DOCS_GAME_SDK_LOBBIES/search) to build a stable list of lobbies. This function will then query those lobbies for ones with a matching id.
-
-Returns a `Discord.Lobby`.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|---------------------------|
-| lobbyId | Int64 | the lobby you want to get |
-
-###### Example
-
-```cs
-var lobbyId = 12345;
-
-var query = lobbyManager.GetSearchQuery();
-lobbyManager.Search(query, (res) =>
-{
- if (res == Discord.Result.Ok)
- {
- // This will return you a lobby
- var lobby = lobbyManager.GetLobby(lobbyId);
- }
-});
-
-// This will return NotFound
-var lobby_2 = lobbyManager.GetLobby(lobbyId);
-```
-
-## LobbyMetadataCount
-
-Returns the number of metadata key/value pairs on a given lobby. Used for accessing metadata by iterating over the list.
-
-Returns `Int32`.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|----------------------------------------|
-| lobbyId | Int64 | the lobby you want to get metadata for |
-
-###### Example
-
-```cs
-var count = lobbyManager.LobbyMetadataCount(290926798626357250);
-for (int i = 0; i < count; i++)
-{
- var value = lobbyManager.GetLobbyMetadataKey(290926798626357250, i);
-}
-```
-
-## GetLobbyMetadataKey
-
-Returns the key for the lobby metadata at the given index.
-
-Returns `string`.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|----------------------------------------|
-| lobbyId | Int64 | the lobby you want to get metadata for |
-| index | Int32 | the index of lobby metadata to access |
-
-###### Example
-
-```cs
-var count = lobbyManager.GetLobbyMetadataCount(290926798626357250);
-for (int i = 0; i < count; i++)
-{
- var value = lobbyManager.GetLobbyMetadataKey(290926798626357250, i);
-}
-```
-
-## GetLobbyMetadataValue
-
-Returns lobby metadata value for a given key and id. Can be used with iteration, or direct access by keyname.
-
-###### Parameters
-
-| name | type | description |
-|---------|--------|----------------------------------------|
-| lobbyId | Int64 | the lobby you want to get metadata for |
-| key | string | the key name to access |
-
-###### Example
-
-```cs
-var averageMmr = lobbyManager.GetLobbyMetadataValue(290926798626357250, "metadata.average_mmr");
-```
-
-## MemberCount
-
-Get the number of members in a lobby.
-
-Returns `Int32`.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|---------------------------------------|
-| lobbyId | Int64 | the lobby you want to get members for |
-
-###### Example
-
-```cs
-var count = lobbyManager.MemberCount(290926798626357250);
-for (int i = 0; i < count; i++)
-{
- var id = lobbyManager.GetMemberUserId(290926798626357250, i);
-}
-```
-
-## GetMemberUserId
-
-Gets the user id of the lobby member at the given index.
-
-Returns `Int64`.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|---------------------------------------|
-| lobbyId | Int64 | the lobby you want to get members for |
-| index | Int32 | the index of lobby member to access |
-
-###### Example
-
-```cs
-var count = lobbyManager.MemberCount(290926798626357250);
-for (int i = 0; i < count; i++)
-{
- var id = lobbyManager.GetMemberUserId(290926798626357250, i);
-}
-```
-
-## GetMemberUser
-
-Gets the user object for a given user id.
-
-Returns `Discord.User`.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|---------------------------------------|
-| lobbyId | Int64 | the lobby you want to get members for |
-| userId | Int64 | the user's userId |
-
-###### Example
-
-```cs
-var count = lobbyManager.MemberCount(290926798626357250);
-for (int i = 0; i < count; i++)
-{
- var id = lobbyManager.GetMemberUserId(290926798626357250, i);
- var user = lobbyManager.GetMemberUser(290926798626357250, id);
- Console.WriteLine("Got user {0}", user.Id);
-}
-```
-
-## MemberMetadataCount
-
-Gets the number of metadata key/value pairs for the given lobby member. Used for accessing metadata by iterating over a list.
-
-Returns `Int32`.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|----------------------------------------|
-| lobbyId | Int64 | the lobby the member belongs to |
-| userId | Int64 | the id of the user to get metadata for |
-
-###### Example
-
-```cs
-var count = lobbyManager.MemberMetadataCount(290926798626357250, 53908232506183680);
-for (int i = 0; i < count; i++)
-{
- var key = lobbyManager.GetMemberMetadataKey(290926798626357250, 53908232506183680, i);
-}
-```
-
-## GetMemberMetadataKey
-
-Gets the key for the lobby metadata at the given index on a lobby member.
-
-Returns `string`.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|----------------------------------------|
-| lobbyId | Int64 | the lobby the member belongs to |
-| userId | Int64 | the id of the user to get metadata for |
-| index | Int32 | the index of metadata to access |
-
-###### Example
-
-```cs
-var count = lobbyManager.MemberMetadataCount(290926798626357250, 53908232506183680);
-for (int i = 0; i < count; i++)
-{
- var key = lobbyManager.GetMemberMetadataKey(290926798626357250, 53908232506183680, i);
-}
-```
-
-## GetMemberMetadataValue
-
-Returns user metadata for a given key. Can be used in conjunction with the count and get key functions if you're iterating over metadata. Or you can access the metadata directly by keyname
-
-Returns `string`.
-
-###### Parameters
-
-| name | type | description |
-|---------|--------|----------------------------------------|
-| lobbyId | Int64 | the lobby the member belongs to |
-| userId | Int64 | the id of the user to get metadata for |
-| key | string | the metadata key to access |
-
-###### Example
-
-```cs
-var count = lobbyManager.MemberMetadataCount(290926798626357250, 53908232506183680);
-for (int i = 0; i < count; i++)
-{
- var key = lobbyManager.GetMemberMetadataKey(290926798626357250, 53908232506183680, i);
- var value = lobbyManager.GetMemberMetadataValue(290926798626357250, 53908232506183680, key);
- Console.WriteLine("Value: {0}", value);
-}
-```
-
-## UpdateMember
-
-Updates lobby member info for a given member of the lobby.
-
-Returns `Discord.Result` via callback.
-
-###### Parameters
-
-| name | type | description |
-|-------------|------------------------|-----------------------------------|
-| lobbyId | Int64 | lobby the member belongs to |
-| userId | Int64 | id of the user |
-| transaction | LobbyMemberTransaction | transaction with the changed data |
-
-###### Example
-
-```cs
-var txn = lobbyManager.GetMemberUpdateTransaction();
-txn.SetMetadata("my_mmr", "9999");
-lobbyManager.UpdateMember(290926798626357250, 53908232506183680, txn, (result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Lobby member updated!");
- }
-});
-```
-
-## SendLobbyMessage
-
-Sends a message to the lobby on behalf of the current user. You must be connected to the lobby you are messaging. You should use this function for message sending if you are _not_ using the built in networking layer for the lobby. If you are, you should use [SendNetworkMessage](#DOCS_GAME_SDK_LOBBIES/sendnetworkmessage) instead.
-
-This method has a rate limit of 10 messages per 5 seconds.
-
-Returns a `Discord.Result` via callback.
-
-###### Parameters
-
-| name | type | description |
-|---------|--------|-----------------------------|
-| lobbyId | Int64 | lobby the member belongs to |
-| data | byte[] | the data to send |
-
-###### Example
-
-```cs
-lobbyManager.SendLobbyMessage(290926798626357250, Encoding.UTF8.GetBytes("hey."), (result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Message sent successfully");
- }
-});
-```
-
-## GetSearchQuery
-
-Creates a search object to search available lobbies.
-
-Returns `Discord.LobbySearchQuery`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var search = lobbyManager.GetSearchQuery();
-```
-
-## Search
-
-Searches available lobbies based on the search criteria chosen in the `Discord.LobbySearch` member functions. Lobbies that meet the criteria are then globally filtered, and can be accessed via iteration with `LobbyCount()` and `GetLobbyId()`. The callback fires when the list of lobbies is stable and ready for iteration.
-
-You do not necessarily need to access the filtered lobbies within the context of the result callback, but it may make it easier for the sake of asynchronous timing.
-
-Returns `Discord.Result` via callback.
-
-###### Parameters
-
-| name | type | description |
-|--------|-------------|---------------------|
-| search | LobbySearch | the search criteria |
-
-###### Example
-
-```cs
-var search = lobbyManger.GetSearchQuery();
-search.Filter("metadata.matchmaking_rating", LobbySearchComparison.GreaterThan, LobbySearchCast.Number, "455");
-search.Sort("metadata.matchmaking_rating", LobbySearchCast.Number, "456");
-search.Limit(10);
-lobbyManager.Search(search, (result) =>
-{
- if (result == Discord.Result.Ok)
- {
- var count = lobbyManager.LobbyCount();
- Console.WriteLine("There are {0} lobbies that match your search criteria", count);
- }
-});
-```
-
-## LobbyCount
-
-Get the number of lobbies that match the search.
-
-Returns `Int32`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-lobbyManager.Search(search, () =>
-{
- var count = lobbyManager.LobbyCount();
- Console.WriteLine("There are {0} lobbies that match your search criteria", count);
-});
-```
-
-## GetLobbyId
-
-Returns the id for the lobby at the given index.
-
-Returns `Int64`.
-
-###### Parameters
-
-| name | type | description |
-|-------|-------|--------------------------------------------------|
-| index | Int32 | the index at which to access the list of lobbies |
-
-###### Example
-
-```cs
-lobbyManager.Search(search, () =>
-{
- var count = lobbyManager.LobbyCount();
- for (int i = 0; i < count; i++)
- {
- var id = lobbyManager.GetLobbyId(i);
- Console.WriteLine("Found lobby {0}", id);
- }
-});
-```
-
-## ConnectVoice
-
-Connects to the voice channel of the current lobby. When connected to voice, the user can open their Discord overlay to see a list of other users with whom they are in voice, allowing them to mute/deafen themselves as well as mute/adjust the volume of other lobby members.
-
-You can also allow users to adjust voice settings for your game with [Overlay OpenVoiceSettings](#DOCS_GAME_SDK_OVERLAY/openvoicesettings).
-
-When integrating lobby voice into your game, be thoughtful about the user's experience. Auto-joining to voice can be jarring for users who may not be expecting it. We recommend voice always being opt-in, or at least that you provide an option for a player to choose whether or not to auto-join the voice channel of lobbies they join.
-
-Returns `Discord.Result` via callback.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|---------------------------|
-| lobbyId | Int64 | lobby to voice connect to |
-
-###### Example
-
-```cs
-lobbyManager.ConnectVoice(290926798626357250, (result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Voice connected!");
- }
-});
-```
-
-## DisconnectVoice
-
-Disconnects from the voice channel of a given lobby.
-
-Returns `Discord.Result` via callback.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|--------------------------------|
-| lobbyId | Int64 | lobby to voice disconnect from |
-
-###### Example
-
-```cs
-lobbyManager.DisconnectVoice(290926798626357250, (result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Voice disconnected!");
- }
-});
-```
-
-## OnLobbyUpdate
-
-Fires when a lobby is updated.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|--------------------|
-| lobbyId | Int64 | lobby that updated |
-
-###### Example
-
-```cs
-lobbyManager.OnLobbyUpdate += (lobbyID) =>
-{
- Console.WriteLine("lobby successfully updated: {0}", lobbyID);
-};
-```
-
-## OnLobbyDelete
-
-Fired when a lobby is deleted.
-
-###### Parameters
-
-| name | type | description |
-|---------|--------|------------------------------------------------|
-| lobbyId | Int64 | lobby that was deleted |
-| reason | string | reason for deletion - this is a system message |
-
-###### Example
-
-```cs
-lobbyManager.OnLobbyDelete += (lobbyID, reason) =>
-{
- Console.WriteLine("lobby successfully deleted: {0} with reason: {1}", lobbyID, reason);
-};
-```
-
-## OnMemberConnect
-
-Fires when a new member joins the lobby.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|-----------------------|
-| lobbyId | Int64 | lobby the user joined |
-| userId | Int64 | user that joined |
-
-###### Example
-
-```cs
-lobbyManager.OnMemberConnect += (lobbyID, userID) =>
-{
- Console.WriteLine("user {0} connected to lobby: {1}", userID, lobbyID);
-};
-```
-
-## OnMemberUpdate
-
-Fires when data for a lobby member is updated.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|-------------------------------|
-| lobbyId | Int64 | lobby the user is a member of |
-| userId | Int64 | user that was updated |
-
-###### Example
-
-```cs
-lobbyManager.OnMemberUpdate += (lobbyID, userID) =>
-{
- Console.WriteLine("user {0} got updated in lobby: {1}", userID, lobbyID);
-};
-```
-
-## OnMemberDisconnect
-
-Fires when a member leaves the lobby.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|--------------------------------|
-| lobbyId | Int64 | lobby the user was a member of |
-| userId | Int64 | user that left |
-
-###### Example
-
-```cs
-lobbyManager.OnMemberDisconnect += (lobbyID, userID) =>
-{
- Console.WriteLine("user {0} disconnected from lobby: {1}", userID, lobbyID);
-};
-```
-
-## OnLobbyMessage
-
-Fires when a message is sent to the lobby.
-
-###### Parameters
-
-| name | type | description |
-|---------|--------|------------------------------|
-| lobbyId | Int64 | lobby the message is sent to |
-| userId | Int64 | user that sent the message |
-| data | byte[] | the message contents |
-
-###### Example
-
-```cs
-lobbyManager.OnLobbyMessage += (lobbyID, userID, data) =>
-{
- Console.WriteLine("lobby message: {0}, user who sent the message: {1}, Containing: {2}", lobbyID, userID, Encoding.UTF8.GetString(data));
-};
-```
-
-## OnSpeaking
-
-Fires when a user connected to voice starts or stops speaking.
-
-###### Parameters
-
-| name | type | description |
-|----------|-------|---------------------------------------------------------|
-| lobbyId | Int64 | lobby the user is connected to |
-| userId | Int64 | user in voice |
-| speaking | bool | `true` == started speaking, `false` == stopped speaking |
-
-###### Example
-
-```cs
-lobbyManager.OnSpeaking += (lobbyID, userID, speaking) =>
-{
- Console.WriteLine("lobby speaking: {0} {1} {2}", lobbyID, userID, speaking);
-};
-```
-
-## Connecting to Lobbies
-
-In the preceding section, you probably noticed there are a couple different methods for connecting to a lobby: `Connect()` and `ConnectWithActivitySecret()`. Lobbies in Discord are even more useful when hooked together with Activities/Rich Presence functionality; they give you everything you need to create an awesome game invite system.
-
-If you are creating lobbies for users in the game client, and not on a backend server, consider using `GetLobbyActivitySecret` and `ConnectWithActivitySecret()`. `GetLobbyActivitySecret()` will return you a unique secret for the lobby concatenated with the lobby's id. You can pipe this value directly to the `Secrets.Join` field of the `Activity` payload. Then, when a user receives the secret, their client can call `ConnectWithActivitySecret()` with just the secret; the lobby id is parsed out automatically. This saves you the effort of concatenating the secret + id together yourself and then parsing them out again. As a code example:
-
-```cs
-var discord = new Discord.Discord(clientId, Discord.CreateFlags.Default);
-var lobbyManager = discord.GetLobbyManager();
-var activityManager = discord.GetActivityManager();
-
-// Create a lobby
-var txn = lobbyManager.GetLobbyCreateTransaction();
-txn.SetCapacity(5);
-txn.SetType(Discord.LobbyType.Private);
-
-lobbyManager.CreateLobby(txn, (Discord.Result result, ref Discord.Lobby lobby) =>
-{
- // Get the special activity secret
- var secret = lobbyManager.GetLobbyActivitySecret(lobby.id);
-
- // Create a new activity
- // Set the party id to the lobby id, so everyone in the lobby has the same value
- // Set the join secret to the special activity secret
- var activity = new Discord.Activity
- {
- Party =
- {
- Id = lobby.id,
- Size = {
- CurrentSize = 1,
- MaxSize = 5
- }
- },
- Secrets =
- {
- Join = secret
- }
- };
-
- activityManager.UpdateActivity(activity, (result) =>
- {
- // Now, you can send chat invites, or others can ask to join
- // When other clients receive the OnActivityJoin() event, they'll receive the special activity secret
- // They can then directly call lobbyManager.ConnectLobbyWithActivitySecret() and be put into the lobby together
- })
-});
-```
-
-If you are creating lobbies with your own backend system (see the section below), this method may not be useful for you. In that case, you can use `Connect()` and pass the lobby id and secret as you normally would. If you're hooking up to Activities, just make sure you send both the lobby secret and the lobby id in the `Secrets.Join` field, so anyone who tries to join has the right data.
-
-### Example: Search for a Lobby, Connect, and Join Voice
-
-```cs
-var discord = new Discord.Discord(clientId, Discord.CreateFlags.Default);
-
-// Search lobbies.
-var query = lobbyManager.GetSearchQuery();
-
-// Filter by a metadata value.
-query.Filter("metadata.ELO", Discord.LobbySearchComparison.EqualTo, Discord.LobbySearchCast.Number, "1337");
-
-// Only return 1 result max.
-query.Limit(1);
-
-lobbyManager.Search(query, () =>
-{
- Console.WriteLine("search returned {0} lobbies", lobbyManager.LobbyCount());
-
- if (lobbyManager.LobbyCount() == 1)
- {
- Console.WriteLine("first lobby: {0}", lobbyManager.GetLobbyId(0));
- }
-
- // Get the id of the lobby, and connect to voice
- var id = lobbyManager.GetLobbyId(0);
- lobbyManager.ConnectVoice(id, (result) =>
- {
- Console.WriteLine("Connected to voice!");
- });
-});
-```
-
-## Example: Crossplayish
-
-So, an explanation. Because the DLL that you ship with your game is a stub that calls out to the local Discord client for actual operations, the SDK does not necessarily care if the game was launched from Discord. As long as the player launching the game:
-
-1. Has Discord installed
-2. Has a Discord account
-3. Has logged into Discord on their machine (whether or not Discord is open)
-
-The SDK will function as if the game were launched from Discord and everything will work; if Discord is not currently launched, the SDK will launch it.
-
-That means that if Player A is launching Your Amazing Game from Discord, and Player B is launching it from Other Cool But Not As Cool As Discord Game Store, as long as Player B meets the above criteria, both players can play with each other using Discord's lobbies + networking functions. If the SDK is not able to launch Discord for Player B—maybe they've never installed/used Discord before!—you'll get an error saying as much. We're not saying what you _should_ do, but hey, wouldn't this make a really neat in-game touchpoint for your players to join their friends on Discord, and maybe even join your game's [verified server](https://discord.com/verification)?
-
-OK so this wasn't really a code example, but I think you get how this works.
-
-## The API Way
-
-Below are the API endpoints and the parameters they accept. If you choose to interface directly with the Discord API, you will need a bot token. This is a special authorization token with which your application can access Discord's HTTP API. Head on over to [your app's settings](https://discord.com/developers/applications), and navigate to the **Bot** page on the sidebar. From there, mutter _abra kadabra_ and reveal the token. This token is used as an authorization header against our API like so:
-
-```
-curl -x POST -h "Authorization: Bot " https://discord.com/api/some-route/that-does-a-thing
-```
-
-> info
-> Make sure to prepend your token with "Bot"!
-
-Here are the routes; they all expect JSON bodies. Also, hey, while you're here. You've got a bot token. You're looking at our API. You should check out all the other [awesome stuff](https://discord.com/developers/docs/intro) you can do with it!
-
-## Create Lobby % POST /lobbies
-
-Creates a new lobby. Returns an object similar to the SDK `Lobby` struct, documented below.
-
-To get a list of valid regions, call the [List Voice Regions](https://discord.com/developers/docs/resources/voice#list-voice-regions) endpoint.
-
-###### Parameters
-
-| name | type | description |
-|----------------|-----------|------------------------------------------------------------------------------------------------------|
-| application_id | string | your application id |
-| type | LobbyType | the type of lobby |
-| metadata | dict | metadata for the lobby - key/value pairs with types `string` |
-| capacity | int | max lobby capacity with a default of 16 |
-| region | string | the region in which to make the lobby - defaults to the region of the requesting server's IP address |
-
-###### Return Object
-
-```json
-{
- "capacity": 10,
- "region": "us-west",
- "secret": "400316b221351324",
- "application_id": "299996444748734465",
- "metadata": {
- "a": "wow",
- "b": "some test metadata"
- },
- "type": 1,
- "id": "469317204969993265",
- "owner_id": "53908232599983680"
-}
-```
-
-## Update Lobby % PATCH /lobbies/{lobby.id#DOCS_LOBBIES/data-models-lobby-struct}
-
-Updates a lobby.
-
-###### Parameters
-
-| name | type | description |
-|----------|-----------|--------------------------------------------------------------|
-| type | LobbyType | the type of lobby |
-| metadata | dict | metadata for the lobby - key/value pairs with types `string` |
-| capacity | int | max lobby capacity with a default of 16 |
-
-## Delete Lobby % DELETE /lobbies/{lobby.id#DOCS_GAME_SDK_LOBBIES/data-models-lobby-struct}
-
-Deletes a lobby.
-
-## Update Lobby Member % PATCH /lobbies/{lobby.id#DOCS_GAME_SDK_LOBBIES/data-models-lobby-struct}/members/{user.id#DOCS_RESOURCES_USER/user-object}
-
-Updates the metadata for a lobby member.
-
-###### Parameters
-
-| name | type | description |
-|----------|------|---------------------------------------------------------------------|
-| metadata | dict | metadata for the lobby member - key/value pairs with types `string` |
-
-## Create Lobby Search % POST /lobbies/search
-
-Creates a lobby search for matchmaking around given criteria.
-
-###### Parameters
-
-| name | type | description |
-|----------------|-------------------------------|------------------------------------------|
-| application_id | string | your application id |
-| filter | array of SearchFilter objects | the filter to check against |
-| sort | array of SearchSort objects | how to sort the results |
-| limit | int | limit of lobbies returned, default of 25 |
-
-###### SearchFilter Object
-
-| name | type | description |
-|------------|------------------|---------------------------------------------------|
-| key | string | the metadata key to search |
-| value | string | the value of the metadata key to validate against |
-| cast | SearchCast | the type to cast `value` as |
-| comparison | SearchComparison | how to compare the metadata values |
-
-###### SearchComparison Types
-
-| name | value |
-|--------------------------|-------|
-| EQUAL_TO_OR_LESS_THAN | -2 |
-| LESS_THAN | -1 |
-| EQUAL | 0 |
-| EQUAL_TO_OR_GREATER_THAN | 1 |
-| GREATER_THAN | 2 |
-| NOT_EQUAL | 3 |
-
-###### SearchSort Object
-
-| name | type | description |
-|------------|------------|-------------------------------------------------------------------------|
-| key | string | the metadata key on which to sort lobbies that meet the search criteria |
-| cast | SearchCast | the type to cast `value` as |
-| near_value | string | the value around which to sort the key |
-
-###### SearchCast Types
-
-| name | value |
-|--------|-------|
-| STRING | 1 |
-| NUMBER | 2 |
-
-## Send Lobby Data % POST /lobbies/{lobby.id#DOCS_GAME_SDK_LOBBIES/data-models-lobby-struct}/send
-
-Sends a message to the lobby, fanning it out to other lobby members.
-
-This endpoints accepts a UTF8 string. If your message is already a string, you're good to go! If you want to send binary, you can send it to this endpoint as a base64 encoded data uri.
-
-###### Parameters
-
-| name | type | description |
-|------|--------|---------------------------------------------|
-| data | string | a message to be sent to other lobby members |
-
-## Integrated Networking
-
-Discord lobbies have the option of being used with a wrapped networking layer, allowing you to start sending packets quickly and easily without needing to do state management around routes, peer IDs, member metadata, and the like.
-
-This layer allows you to easily connect to the network and open channels to all lobby members with one function call. You can then send network messages to users by their user ID, easily retrieved via lobby methods.
-
-We take care of all the route updating for you, so you can get up and running quickly and easily. If you'd like to see how the lower level networking functionality works, or want to try it yourself so you can tweak it to your liking, check out [Networking](#DOCS_GAME_SDK_NETWORKING/);
-
-## ConnectNetwork
-
-Connects to the networking layer for the given lobby ID. Call this when connecting to the lobby.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|--------------------------------|
-| lobbyId | Int64 | the ID of the lobby you are in |
-
-###### Example
-
-```cs
-lobbyManager.ConnectLobby(lobbyId, (result, lobby) =>
-{
- lobbyManager.ConnectNetwork(lobby.Id);
-});
-```
-
-## DisconnectNetwork
-
-Disconnects from the networking layer for the given lobby ID.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|---------|-------|--------------------------------|
-| lobbyId | Int64 | the ID of the lobby you are in |
-
-###### Example
-
-```cs
-lobbyManager.DisconnectNetwork(lobby.Id);
-```
-
-## FlushNetwork
-
-Flushes the network. Call this when you're done sending messages. In Unity, this should be in `LateUpdate()`.
-
-Returns `void`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-void LateUpdate()
-{
- var lobbyManager = discord.GetLobbyManager();
- lobbyManager.FlushNetwork();
-}
-```
-
-## OpenNetworkChannel
-
-Opens a network channel to all users in a lobby on the given channel number. No need to iterate over everyone!
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|-----------|-------|------------------------------------------------------|
-| lobbyId | Int64 | the ID of the lobby you are in |
-| channelId | byte | the channel on which to connect |
-| reliable | bool | whether the channel should be unreliable or reliable |
-
-###### Example
-
-```cs
-var lobbyManager = discord.GetLobbyManager();
-lobbyManager.ConnectLobby(lobbyId, (result, lobby) =>
-{
- lobbyManager.ConnectNetwork(lobby.Id);
- lobbyManager.OpenNetworkChannel(lobby.Id, 0, true);
-});
-```
-
-## SendNetworkMessage
-
-Sends a network message to the given user ID that is a member of the given lobby ID over the given channel ID.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|-----------|--------|-----------------------------------------|
-| lobbyId | Int64 | the ID of the lobby you are in |
-| userId | Int64 | the ID of the user to send a message to |
-| channelId | byte | the channel on which to connect |
-| data | byte[] | the message to send |
-
-###### Example
-
-```cs
-var lobbyManager = discord.GetLobbyManager();
-lobbyManager.ConnectLobby(lobbyId, (result, lobby) =>
-{
- lobbyManager.ConnectNetwork(lobby.Id);
- lobbyManager.OpenNetworkChannel(lobby.Id, 0, true);
- for (int i = 0; i < lobbyManager.MemberCount(); i++)
- {
- var userId = lobbyManager.GetMemberUserId(i);
- lobbyManager.SendNetworkMessage(lobby.Id, userId, 0, System.Text.Encoding.UTF8.GetBytes("Hello!"));
- }
-});
-```
-
-## OnNetworkMessage
-
-Fires when the user receives a message from the lobby's networking layer.
-
-###### Parameters
-
-| name | type | description |
-|-----------|--------|-----------------------------------------|
-| lobbyId | Int64 | the ID of the lobby you are in |
-| userId | Int64 | the ID of the user who sent the message |
-| channelId | byte | the channel the message was sent on |
-| data | byte[] | the message |
-
-## Example: Networking the Easy Way
-
-```cs
-// We can create a helper method to easily connect to the networking layer of the lobby
-public void InitNetworking(Int64 lobbyId)
-{
- // First, connect to the lobby network layer
- var lobbyManager = discord.GetLobbyManager();
- lobbyManager.ConnectNetwork(lobbyId);
-
- // Next, deterministically open our channels
- // Reliable on 0, unreliable on 1
- lobbyManager.OpenNetworkChannel(lobbyId, 0, true);
- lobbyManager.OpenNetworkChannel(lobbyId, 1, false);
-
- // We're ready to go!
-}
-
-// Let's say we got a game invite from Rich Presence
-activityManager.OnActivityJoin += secret =>
-{
- var lobbyManager = discord.GetLobbyManager();
- lobbyManager.ConnectLobbyWithActivitySecret(secret, (Discord.Result result, ref Discord.Lobby lobby) =>
- {
- // Connect to networking
- InitNetworking(lobby.Id);
-
- // Say hello!
- for (int i = 0; i < lobbyManager.MemberCount(); i++)
- {
- var userId = lobbyManager.GetMemberUserId(i);
- lobbyManager.SendNetworkMessage(lobby.Id, userId, 0, System.Text.Encoding.UTF8.GetBytes("Hello!"));
- }
- });
-}
-```
diff --git a/docs/game_sdk/Networking.md b/docs/game_sdk/Networking.md
deleted file mode 100644
index d2c8b2ae26..0000000000
--- a/docs/game_sdk/Networking.md
+++ /dev/null
@@ -1,377 +0,0 @@
-# Networking
-
-> info
-> Need help with the SDK? Talk to us in the [Discord Developers Server](https://discord.gg/discord-developers)!
-
-> danger
-> The GameSDK's Achievements, Applications, Voice, Images, Lobbies, Networking, Storage, and Store (purchases and discounts) features have been deprecated, and will be decommissioned on **May 2, 2023**. [Read more](#DOCS_CHANGE_LOG/gamesdk-feature-deprecation)
-
-A note before starting: this documentation covers the "low layer" networking level of the Discord GameSDK. What that means is that using the network manager directly affords you the flexibility to update routes, open channels, and handle events directly emitted by the SDK. If you're looking for something a bit easier and faster to integrate, we recommend that you check out the networking wrapper around our lobby documentation: [Integrated Networking](#DOCS_GAME_SDK_LOBBIES/integrated-networking)
-
-Need a networking layer? Have a networking layer! This manager handles all things packets so you can get data from player to player and make your multiplayer...work. It:
-
-- Functions as a connection-oriented, TCP-like API, but over UDP!
-- Supports "reliable" and "unreliable" connections
- - Packets with loot in them always get there, but player positioning can be eventually consistent
-- Features P2P-like connections, but routed through Discord's high-end server infrastructure
- - All the benefits of direct connections, without the IP leaks!
-- Is encrypted!
-
-An important note to make here is that our networking layer **is not peer-to-peer**. Discord has always promised that we will not leak your IP, and we promise to keep it that way. Though it seems like you are connected directly to another user, it routes through Discord's servers in the middle, ensuring both security and robust networking thanks to our servers.
-
-## GetPeerId
-
-Get the networking peer ID for the current user, allowing other users to send packets to them.
-
-Returns a `UInt64`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var myPeerId = networkManager.GetPeerId();
-```
-
-## Flush
-
-Flushes the network. Run this at the end of your game's loop, once you've finished sending all you need to send. In Unity, for example, stick this in `LateUpdate()`.
-
-Returns `void`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-void LateUpdate()
-{
- networkManager.Flush();
-}
-```
-
-## OpenChannel
-
-Opens a channel to a user with their given peer ID on the given channel number.
-
-Unreliable channels—`reliable = false`—should be used for loss-tolerant data, like player positioning in the world. Reliable channels—`reliable = true`—should be used for data that _must_ get to the user, like loot drops!
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|-----------|--------|------------------------------------------------------|
-| peerId | UInt64 | the peerId of the user to connect to |
-| channelId | byte | the channel on which to connect |
-| reliable | bool | whether the channel should be unreliable or reliable |
-
-###### Example
-
-```cs
-var userId = 53908232506183680;
-var lobbyId = 290926798626357250;
-
-var rawPeerId = lobbyManager.GetMemberMetadataValue(lobbyId, userId, "metadata.peer_id");
-// Metadata is stored as a string, so we need to make it an integer for OpenChannel
-var peerId = System.Convert.ToUInt64(rawPeerId);
-networkManager.OpenChannel(peerId, 0, false);
-```
-
-## OpenPeer
-
-Opens a network connection to another Discord user.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|--------|--------|----------------------------------------------|
-| peerId | UInt64 | the peerId of the user to connect to |
-| route | string | the route the user is currently broadcasting |
-
-###### Example
-
-```cs
-var userId = 53908232506183680;
-var lobbyId = 290926798626357250;
-
-var rawPeerId = lobbyManager.GetMemberMetadataValue(lobbyId, userId, "metadata.peer_id");
-// Metadata is stored as a string, so we need to make it an integer for OpenChannel
-var peerId = System.Convert.ToUInt64(rawPeerId);
-var route = lobbyManager.GetMemberMetadataValue(lobbyId, userId, "metadata.route");
-networkManager.OpenPeer(peerId, route);
-```
-
-## UpdatePeer
-
-Updates the network connection to another Discord user. You'll want to call this when notified that the route for a user to which you are connected has changed, most likely from a lobby member update event.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|--------|--------|----------------------------|
-| peerId | UInt64 | the user's peerId |
-| route | string | the new route for the user |
-
-###### Example
-
-```cs
-lobbyManager.OnMemberUpdate += (lobbyId, userId) =>
-{
- var rawPeerId = lobbyManager.GetMemberMetadataValue(lobbyId, userId, "metadata.peer_id");
- // Metadata is stored as a string, so we need to make it an integer for OpenChannel
- var peerId = System.Convert.ToUInt64(rawPeerId);
- var newRoute = lobbyManager.GetMemberMetadataValue(lobbyId, userId, "metadata.route");
- networkManager.UpdatePeer(peerId, newRoute);
-}
-```
-
-## SendMessage
-
-Sends data to a given peer ID through the given channel.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|-----------|--------|---------------------------------|
-| peerId | UInt64 | the peer id to connect to |
-| channelId | byte | the channel on which to connect |
-| data | byte[] | the data to send |
-
-###### Example
-
-```cs
-var userId = 53908232506183680;
-var lobbyId = 290926798626357250;
-var rawPeerId = lobbyManager.GetMemberMetadataValue(lobbyId, userId, "metadata.peer_id");
-// Metadata is stored as a string, so we need to make it an integer for OpenChannel
-var peerId = System.Convert.ToUInt64(rawPeerId);
-
-byte[] lootDrops = GameEngine.GetLootData();
-networkManager.SendMessage(peerId, 1, lootDrops);
-```
-
-## CloseChannel
-
-Close the connection to a given user by peerId on the given channel.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|-----------|--------|-------------------------------------------|
-| peerId | UInt64 | the peerId of the user to disconnect from |
-| channelId | byte | the route to close |
-
-###### Example
-
-```cs
-var userId = 53908232506183680;
-var lobbyId = 290926798626357250;
-
-var rawPeerId = lobbyManager.GetMemberMetadataValue(lobbyId, userId, "metadata.peer_id");
-// Metadata is stored as a string, so we need to make it an integer for OpenChannel
-var peerId = System.Convert.ToUInt64(rawPeerId);
-networkManager.CloseChannel(peerId, 0);
-Console.WriteLine("Channel {0} to {1} closed", 0, peerId);
-```
-
-## ClosePeer
-
-Disconnects the network session to another Discord user.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|--------|--------|-------------------|
-| peerId | UInt64 | the user's peerId |
-
-###### Example
-
-```cs
-var userId = 53908232506183680;
-var lobbyId = 290926798626357250;
-
-var rawPeerId = lobbyManager.GetMemberMetadataValue(lobbyId, userId, "metadata.peer_id");
-// Metadata is stored as a string, so we need to make it an integer for OpenChannel
-var peerId = System.Convert.ToUInt64(rawPeerId);
-networkManager.ClosePeer(peerId);
-Console.WriteLine("Connection to {0} closed", peerId);
-```
-
-## OnMessage
-
-Fires when you receive data from another user. This callback will only fire if you already have an open channel with the user sending you data. Make sure you're running `RunCallbacks()` in your game loop, or you'll never get data!
-
-###### Parameters
-
-| name | type | description |
-|-----------|--------|----------------------------|
-| peerId | UInt64 | the peer id of the sender |
-| channelId | byte | the channel it was sent on |
-| data | byte[] | the data sent |
-
-###### Example
-
-```cs
-networkManager.OnMessage += (peerId, channel, data) =>
-{
- var stringData = Encoding.UTF8.GetString(data);
- Console.WriteLine("Message from {0}: {1}", peerId, stringData)
-}
-```
-
-## OnRouteUpdate
-
-Fires when your networking route has changed. You should broadcast to other users to whom you are connected that this has changed, probably by updating your lobby member metadata for others to receive.
-
-###### Parameters
-
-| name | type | description |
-|-------|--------|---------------------------|
-| route | string | the new route to the user |
-
-###### Example
-
-```cs
-networkManager.OnRouteUpdate += route =>
-{
- var currentUser = userManager.GetCurrentUser();
- var lobbyId = 290926798626357250;
-
- var txn = lobbyManager.GetMemberUpdateTransaction(lobbyId, currentUser.Id);
- txn.SetMetadata("route", route);
- lobbyManager.UpdateMember(lobbyId, currentUser.Id, txn, (result) =>
- {
- // Who needs error handling anyway
- Console.WriteLine(result);
- });
-}
-```
-
-## Flush vs RunCallbacks
-
-A quick note here may be helpful for the two functions that should be called continuously in your game loop: `discord.RunCallbacks()` and `networkManager.Flush()`. `RunCallbacks()` pumps the SDK's event loop, sending any newly-received data down the SDK tubes to your game. For this reason, you should call it at the beginning of your game loop; that way, any new data is handled immediately by callbacks you've registered. In Unity, for example, this goes in `Update()`.
-
-`Flush()` is specific to the network manager. It actually _writes_ the packets out to the stream. You should call this at the _end_ of your game loop as a way of saying "OK, I'm done with networking stuff, go send all the stuff to people who need it". In Unity, for example, this goes in `LateUpdate()`.
-
-## Connecting to Each Other
-
-This manager is built around the concept of routes between players, and then channels on those routes. Player A opens a route to Player B. This route will change, most commonly if the user's external IP address changes. As that route changes, the player will receive `OnRouteUpdate` events. They should then alert other lobby members that their route has changed by updating their lobbymetadata. Other lobby members will see those updates from the `OnLobbyMemberUpdate` event, and can call `UpdateRoute()` accordingly. A user's route could change frequently, so architect your system anticipating frequent route changes and updates.
-
-Once Player A has a route open to Player B, Player A then opens a channel to Player B, and Player B does the same to Player A. Channels are the pipes down which data is actually sent. These two users can now send data back and forth to each other with `SendMessage()` and receive it with `OnMessage`.
-
-In order to properly send and receive data between A and B, both users need to have **the same type of channel** open to each other **on the same channel number**. If A has Reliable Channel 4 open to B, B also needs Reliable Channel 4 open to A.
-
-## Example: Connecting to Another Player in a Lobby
-
-```cs
-var discord = new Discord.Discord(clientId, (UInt64)Discord.CreateFlags.Default);
-
-// Join a lobby with another user in it
-// Get their peer id, and connect to them
-
-var networkManager = discord.GetNetworkManager();
-var lobbyManager = discord.GetLobbyManager();
-var userManager = discord.GetUserManager();
-
-Discord.User currentUser;
-var otherUserPeerId;
-var lobbyId;
-
-// Get yourself
-currentUser = userManager.GetCurrentUser();
-
-// This will fire once you connect to the lobby
-// Telling you which route is yours
-networkManager.OnRouteUpdate += route =>
-{
- var txn = lobbyManager.GetMemberUpdateTransaction(lobbyId, currentUser.Id);
- txn.SetMetadata("route", route);
- lobbyManager.UpdateMember(lobbyId, currentUser.Id, txn, (result =>
- {
- // Who needs error handling anyway
- Console.WriteLine(result);
- }))
-}
-
-// When other users get new routes, they'll update their metadata
-// Fetch it and update their route
-lobbyManager.OnMemberUpdate += (lobbyId, userId) =>
-{
- var rawPeerId = lobbyManager.GetMemberMetadataValue(lobbyId, userId, "peer_id");
- // Metadata is stored as a string, so we need to make it an integer for OpenChannel
- var peerId = System.Convert.ToUInt64(rawPeerId);
- var newRoute = lobbyManager.GetMemberMetadataValue(lobbyId, userId, "route");
- lobbyManager.UpdatePeer(peerId, newRoute);
-}
-
-// Connect to lobby with an id of 12345 and a secret of "password"
-// This may occur in a generated lobby search, when a user needs to input a password to connect
-lobbyManager.ConnectLobby(12345, "password", (Discord.Result x, ref Discord.Lobby lobby) =>
-{
- lobbyId = lobby.Id;
-
- // Add our own peer id to our lobby member metadata
- // So other users can get it to connect to us
- var localPeerId = Convert.ToString(networkManager.GetPeerId());
- var txn = lobbyManager.GetMemberUpdateTransaction(lobby.Id, currentUser.Id);
- txn.SetMetadata("peer_id", localPeerId);
- lobbyManager.UpdateMember(lobby.Id, currentUser.Id, txn, (result) =>
- {
- // Who needs error handling anyway
- Console.WriteLine(result);
- });
-
- // Get the first member in the lobby, assuming someone is already there
- var memberId = lobbyManager.GetMemberUserId(lobby.Id, 0);
-
- // Get their peer id and route from their metadata, added previously
- var rawPeerId = lobbyManager.GetMemberMetadataValue(lobbyId, userId, "peer_id");
- // Metadata is stored as a string, so we need to make it an integer for OpenChannel
- otherUserPeerId = System.Convert.ToUInt64(rawPeerId);
- var otherRoute = lobbyManager.GetMemberMetadataValue(lobby.Id, memberId, "route");
-
- // Connect to them
- networkManager.OpenPeer(otherUserPeerId, otherRoute);
-
-}
-
-// Open an unreliable channel to the user on channel 0
-// And a reliable one on channel 1
-networkManager.OpenChannel(otherUserPeerId, 0, false);
-networkManager.OpenChannel(otherUserPeerId, 1, true);
-
-// An important data packet from our game engine
-byte[] data = GameEngine.GetImportantData();
-
-// Determine if that data is about Player Loot Drops, if so send it on reliable, if not send it on unreliable
-if (isDataAboutPlayerLootDrops(data))
-{
- // This is important and has to get there
- // Send over reliable channel
- networkManager.SendMessage(otherUserPeerId, 1, data);
-}
-else
-{
- // This is eventually consistent data, like the player's position in the world
- // It can be sent over the unreliable channel
- networkManager.SendMessage(otherUserPeerId, 0, data);
-}
-
-// Done; ship it!
-networkManager.Flush();
-```
diff --git a/docs/game_sdk/Overlay.md b/docs/game_sdk/Overlay.md
deleted file mode 100644
index 996025c8aa..0000000000
--- a/docs/game_sdk/Overlay.md
+++ /dev/null
@@ -1,192 +0,0 @@
-# Overlay
-
-> info
-> Need help with the SDK? Talk to us in the [Discord Developers Server](https://discord.gg/discord-developers)!
-
-> warn
-> The overlay is only supported on Windows for DirectX or OpenGL games. Linux, Mac, and games using Vulkan are not supported. [Click here for more info.](https://support.discord.com/hc/en-us/articles/217659737-Games-Overlay-101)
-
-Discord comes with an awesome built-in overlay, and you may want to make use of it for your game. This manager will help you do just that! It:
-
-- Gives you the current state of the overlay for the user
- - Locked, enabled, unlocked, open, closed, etc.
-- Allows you to change that state
-
-## Data Models
-
-###### ActivityActionType Enum
-
-| name | value |
-|----------|-------|
-| Join | 1 |
-| Spectate | 2 |
-
-## IsEnabled
-
-Check whether the user has the overlay enabled or disabled. If the overlay is disabled, all the functionality in this manager will still work. The calls will instead focus the Discord client and show the modal there instead.
-
-Returns a `bool`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-if (!overlaymanager.IsEnabled())
-{
- Console.WriteLine("Overlay is not enabled. Modals will be shown in the Discord client instead");
-}
-```
-
-## IsLocked
-
-Check if the overlay is currently locked or unlocked
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-if (overlayManager.IsLocked())
-{
- overlayManager.SetLocked(true, (res) =>
- {
- Console.WriteLine("Input in the overlay is now accessible again");
- });
-}
-```
-
-## SetLocked
-
-Locks or unlocks input in the overlay. Calling `SetLocked(true);` will also close any modals in the overlay or in-app from things like IAP purchase flows and disallow input.
-
-Returns `Discord.Result` via callback.
-
-###### Parameters
-
-| name | type | description |
-|--------|------|----------------------------|
-| locked | bool | lock or unlock the overlay |
-
-###### Example
-
-```cs
-overlayManager.SetLocked(true, (res) =>
-{
- Console.WriteLine("Overlay has been locked and modals have been closed");
-});
-```
-
-## OpenActivityInvite
-
-Opens the overlay modal for sending game invitations to users, channels, and servers. If you do not have a valid activity with all the required fields, this call will error. See [Activity Action Field Requirements](#DOCS_GAME_SDK_ACTIVITIES/activity-action-field-requirements) for the fields required to have join and spectate invites function properly.
-
-Returns a `Discord.Result` via callback.
-
-###### Parameters
-
-| name | type | description |
-|------|--------------------|-----------------------------|
-| type | ActivityActionType | what type of invite to send |
-
-###### Example
-
-```cs
-overlayManager.OpenActivityInvite(Discord.ActivityActionType.Join, (result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("User is now inviting others to play!");
- }
-});
-```
-
-## OpenGuildInvite
-
-Opens the overlay modal for joining a Discord guild, given its invite code. An invite code for a server may look something like `fortnite` for a verified server—the full invite being `discord.gg/fortnite`—or something like `rjEeUJq` for a non-verified server, the full invite being `discord.gg/rjEeUJq`.
-
-Returns a `Discord.Result` via callback. Note that a successful `Discord.Result` response does not necessarily mean that the user has joined the guild. If you want more granular control over and knowledge about users joining your guild, you may want to look into implementing the [`guilds.join` OAuth2 scope in an authorization code grant](#DOCS_TOPICS_OAUTH2/authorization-code-grant) in conjunction with the [Add Guild Members](#DOCS_RESOURCES_GUILD/add-guild-member) endpoint.
-
-###### Parameters
-
-| name | type | description |
-|------|--------|----------------------------|
-| code | string | an invite code for a guild |
-
-###### Example
-
-```cs
-overlayManager.OpenGuildInvite("rjEeUJq", (result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Invite was valid.");
- }
-});
-```
-
-## OpenVoiceSettings
-
-Opens the overlay widget for voice settings for the currently connected application. These settings are unique to each user within the context of your application. That means that a user can have different favorite voice settings for each of their games!
-
-
-
-Also, when connected to a lobby's voice channel, the overlay will show a widget that allows users to locally mute, deafen, and adjust the volume of others.
-
-
-
-Returns a `Discord.Result` via callback.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-overlayManager.OpenVoiceSettings((result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Overlay is open to the voice settings for your application/")
- }
-})
-```
-
-## OnToggle
-
-Fires when the overlay is locked or unlocked (a.k.a. opened or closed)
-
-###### Parameters
-
-| name | type | description |
-|--------|------|---------------------------------------|
-| locked | bool | is the overlay now locked or unlocked |
-
-###### Example
-
-overlayManager.OnToggle += overlayLock =>
-{
- Console.WriteLine("Overlay Locked: {0}", overlayLock);
-};
-
-## Example: Activate Overlay Invite Modal
-
-```cs
-var discord = new Discord.Discord(clientId, Discord.CreateFlags.Default);
-var overlayManager = discord.GetOverlayManager();
-
-// Invite users to join your game
-overlayManager.OpenActivityInvite(ActivityActionType.Join, (result) =>
-{
- Console.WriteLine("Overlay is now open!");
-})
-```
-
-And that invite modal looks like this!
-
-
diff --git a/docs/game_sdk/Relationships.md b/docs/game_sdk/Relationships.md
deleted file mode 100644
index 37db4c0059..0000000000
--- a/docs/game_sdk/Relationships.md
+++ /dev/null
@@ -1,234 +0,0 @@
-# Relationships
-
-> info
-> Need help with the SDK? Talk to us in the [Discord Developers Server](https://discord.gg/discord-developers)!
-
-This manager helps you access the relationships your players have made on Discord. Unfortunately, it won't help them make relationships IRL. They're on their own for that. It lets you:
-
-- Access a user's relationships
-- Filter those relationships based on a given criteria
-- Build a user's friends list
-
-## First Notes
-
-Relationships on Discord change often; people start and stop playing games, go online, offline, invisible, or otherwise change state. Therefore, there are some important factors to remember when working with this manager. When you are first getting a list of a user's relationships, before you can `Filter()`, you need to wait for the `OnRefresh` callback to fire. This is your indicator that Discord has successfully taken a snapshot of the state of all your relationships at a given moment. Now that you have this snapshot, you can `Filter()` it to build the list that you want, and then iterate over that list to do whatever your game needs to do. Use this to build your initial social graph for a user.
-
-As relationships change, the `OnRelationshipUpdate` event will fire. You can use this to update the user's social graph, changing the status of the other Discord users that you chose to filter, e.g. someone is now online, or now playing the game, or no longer playing.
-
-An example of how to do this properly is at the end of this documentation page.
-
-## Data Models
-
-###### Relationship Struct
-
-| name | type | description |
-|----------|------------------|----------------------------------|
-| Type | RelationshipType | what kind of relationship it is |
-| User | User | the user the relationship is for |
-| Presence | Presence | that user's current presence |
-
-###### RelationshipType Enum
-
-| value | description |
-|-----------------|----------------------------------------------------------------------------------|
-| None | user has no intrinsic relationship |
-| Friend | user is a friend |
-| Blocked | user is blocked |
-| PendingIncoming | user has a pending incoming friend request to connected user |
-| PendingOutgoing | current user has a pending outgoing friend request to user |
-| Implicit | user is not friends, but interacts with current user often (frequency + recency) |
-
-###### Presence Struct
-
-| name | type | description |
-|----------|----------|----------------------------------|
-| Status | Status | the user's current online status |
-| Activity | Activity | the user's current activity |
-
-###### Status Enum
-
-| name | value |
-|--------------|-------|
-| Offline | 0 |
-| Online | 1 |
-| Idle | 2 |
-| DoNotDisturb | 3 |
-
-## Filter
-
-Filters a user's relationship list by a boolean condition.
-
-Returns `void`.
-
-###### Parameters
-
-A function that takes a `Relationship` parameter.
-
-###### Example
-
-```cs
-relationshipsManager.Filter(relationship =>
-{
- return relationship.Presence.Status == Discord.Status.Online;
-});
-```
-
-## Get
-
-Get the relationship between the current user and a given user by id.
-
-Returns a `Relationship`.
-
-###### Parameters
-
-| name | type | description |
-|--------|-------|-----------------------------|
-| userId | Int64 | the id of the user to fetch |
-
-###### Example
-
-```cs
-var friend = relationshipsManager.Get(53908232506183680);
-Console.WriteLine("This is my friend, {0}", friend.User.Username);
-```
-
-## GetAt
-
-Get the relationship at a given index when iterating over a list of relationships.
-
-Returns a `Relationship`.
-
-###### Parameters
-
-| name | type | description |
-|-------|--------|-------------------|
-| index | UInt32 | index in the list |
-
-###### Example
-
-```cs
-for (int i = 0; i < relationshipsManager.Count(); i++)
-{
- var r = relationshipsManager.GetAt(i);
- Console.WriteLine("This person is {0}", r.User.Username);
-}
-```
-
-## Count
-
-Get the number of relationships that match your `Filter()`.
-
-Returns an `Int32`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-for (int i = 0; i < relationshipsManager.Count(); i++)
-{
- var r = relationshipsManager.At(i);
- Console.WriteLine("This person is {0}", r.User.Username);
-}
-```
-
-## OnRefresh
-
-Fires at initialization when Discord has cached a snapshot of the current status of all your relationships. Wait for this to fire before calling `Filter` within its callback.
-
-> warn
-> `OnRefresh` requires the `relationships.read` [OAuth2 scope](https://discord.com/developers/docs/topics/oauth2#shared-resources-oauth2-scopes). The GameSDK will return 0 relationships if the requested user has not authenticated with that scope.
-
-###### Parameters
-
-None
-
-## OnRelationshipUpdate
-
-Fires when a relationship in the filtered list changes, like an updated presence or user attribute.
-
-###### Parameters
-
-| name | type | description |
-|--------------|------------------|-------------------------------|
-| relationship | ref Relationship | the relationship that changed |
-
-###### Example
-
-```cs
-OnRelationshipUpdate += (ref Discord.Relationship relationship) =>
-{
- Console.WriteLine("Who changed? {0}", relationship.User.Id);
-};
-```
-
-## Example: Creating a Friends List
-
-```cs
-var discord = new Discord.Discord(clientId, Discord.CreateFlags.Default);
-var relationshipManager = discord.GetRelationshipManager();
-
-// Assign this handle right away to get the initial relationships update.
-// This callback will only be fired when the whole list is initially loaded or was reset
-
-// Wait for OnRefresh to fire to access a stable list
-// Filter a user's relationship list to be just friends
-// Use this list as your base
-relationshipManager.OnRefresh += () =>
-{
- relationshipManager.Filter((relationship) =>
- {
- return relationship.Type == Discord.RelationshipType.Friend;
- });
-
- // Loop over all friends a user has.
- Console.WriteLine("relationships updated: {0}", relationshipManager.Count());
-
- for (var i = 0; i < relationshipManager.Count(); i++)
- {
- // Get an individual relationship from the list
- var r = relationshipManager.GetAt((uint)i);
- Console.WriteLine("relationships: {0} {1}", r.Type, r.User.Username);
- // Save r off to a list of user's relationships
- }
-}
-
-relationshipManager.OnRelationshipUpdate += (ref Discord.Relationship relationship) =>
-{
- Console.WriteLine("User is {0}", relationship.User.Username);
- // Update the matching user in your previously created list
-}
-```
-
-## Example: Invite Users Who Are Playing the Same Game
-
-```cs
-var discord = new Discord.Discord(clientId, Discord.CreateFlags.Default);
-var relationshipManager = discord.GetRelationshipManager();
-var activityManager = discord.GetActivityManager();
-
-relationshipManager.OnRefresh += () =>
-{
- relationshipManager.Filter((relationship) =>
- {
- // Filter for users who are playing the same game as the current user
- // Is their activity application id the same as my client id?
- return relationship.Presence.Activity.ApplicationId == clientId;
- });
-
- for (var i = 0; i < relationshipManager.Count(); i++)
- {
- // Get an individual relationship from the list
- var r = relationshipManager.GetAt((uint)i);
- Console.WriteLine("relationships: {0} {1}", r.Type, r.User.Username);
-
- // Send them a game invite!
- activityManager.InviteUser(r.User.Id, Discord.ActivityActionType.Join, "Come play with me!", (result) =>
- {
- Console.WriteLine("Invited user {0} to play with you", r.User.Username);
- });
- };
-}
-```
diff --git a/docs/game_sdk/Storage.md b/docs/game_sdk/Storage.md
deleted file mode 100644
index 081309f31a..0000000000
--- a/docs/game_sdk/Storage.md
+++ /dev/null
@@ -1,315 +0,0 @@
-# Storage
-
-> info
-> Need help with the SDK? Talk to us in the [Discord Developers Server](https://discord.gg/discord-developers)!
-
-> warn
-> Selling SKUs on Discord has now been discontinued as of March 1, 2022. [Read here for more info.](https://support-dev.discord.com/hc/en-us/articles/6309018858647-Self-serve-Game-Selling-Deprecation)
-
-> danger
-> The GameSDK's Achievements, Applications, Voice, Images, Lobbies, Networking, Storage, and Store (purchases and discounts) features have been deprecated, and will be decommissioned on **May 2, 2023**. [Read more](#DOCS_CHANGE_LOG/gamesdk-feature-deprecation)
-
-We've been told that people playing games want to save their progress as they go, allowing them to come back where they left off and continue their epic journey of power.
-
-Yeah, roguelikes. Even you.
-
-Discord's storage manager lets you save data mapped to a key for easy reading, writing, and deleting both synchronously and asynchronously. It's saved to a super special directory, the Holy Grail of file mappings, that's unique per Discord user — no need to worry about your little brother overwriting your save file.
-
-Creating this manager will also spawn an IO thread for async reads and writes, so unless you really want to be blocking, you don't need to be!
-
-## Cloud Saves
-
-If you want to take that save data on your players' computers and save it to those **BIG COMPUTERS** in the cloud, look no further! All you need to do is head over to your manifest config file and set the following property:
-
-```js
-{
- "storage": {
- "sync": true
- }
-}
-```
-
-Yup, that's it!
-
-## Data Models
-
-###### FileStat Struct
-
-| name | type | description |
-|--------------|--------|----------------------------------------------|
-| Filename | string | the name of the file |
-| Size | UInt64 | the size of the file |
-| LastModified | UInt64 | timestamp of when the file was last modified |
-
-## GetPath
-
-> info
-> Value from environment variable `DISCORD_STORAGE_PATH`
-
-Returns the filepath to which Discord saves files if you were to use the SDK's storage manager. Discord has branch-specific, user-specific saves, so you and your little brother will never overwrite each others' save files. If your game already has save file writing logic, you can use this method to get that user-specific path and help users protect their save files.
-
-Returns a `string`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var savePath = storageManager.GetPath();
-Console.WriteLine("You should write your save files to {0}", savePath);
-```
-
-## Read
-
-Reads data synchronously from the game's allocated save file into a buffer. The file is mapped by key value pairs, and this function will read data that exists for the given key name.
-
-Returns a `UInt32`.
-
-###### Parameters
-
-| name | type | description |
-|------|--------|------------------------------------|
-| name | string | the key name to read from the file |
-| data | byte[] | the buffer to read into |
-
-## ReadAsync
-
-Reads data asynchronously from the game's allocated save file into a buffer.
-
-Returns a `Discord.Result` and a `byte[]` containing the data via callback.
-
-###### Parameters
-
-| name | type | description |
-|------|--------|------------------------------------|
-| name | string | the key name to read from the file |
-
-###### Example
-
-```cs
-storeManager.ReadAsync("high_score", (result, data) =>
-{
- if (result == Discord.Result.OK) {
- LoadHighScore(data);
- }
-});
-```
-
-## ReadAsyncPartial
-
-Reads data asynchronously from the game's allocated save file into a buffer, starting at a given offset and up to a given length.
-
-Returns a `Discord.Result` and `byte[]` containing the data via callback.
-
-###### Parameters
-
-| name | type | description |
-|--------|--------|--------------------------------------|
-| name | string | the key name to read from the file |
-| offset | UInt64 | the offset at which to start reading |
-| length | UInt64 | the length to read |
-
-###### Example
-
-```cs
-storeManager.ReadAsyncPartial("high_score", 10, 8, (result, data) =>
-{
- if (result == Discord.Result.OK) {
- LoadHighScore(data);
- }
-});
-```
-
-## Write
-
-Writes data synchronously to disk, under the given key name.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|------|--------|-----------------------------|
-| name | string | the key name to write under |
-| data | byte[] | the data to write |
-
-###### Example
-
-```cs
-storageManager.Write("high_score", Encoding.UTF8.GetBytes("9999"));
-```
-
-## WriteAsync
-
-Writes data asynchronously to disk under the given keyname.
-
-Returns a `Discord.Result` via callback.
-
-###### Parameters
-
-| name | type | description |
-|------|--------|-----------------------------|
-| name | string | the key name to write under |
-| data | byte[] | the data to write |
-
-###### Example
-
-```cs
-storageManager.WriteAsync("high_score", Encoding.UTF8.GetBytes("9999"), (result) =>
-{
- if (result == Discord.Result.OK)
- {
- Console.WriteLine("Wrote data");
- }
-});
-```
-
-## Delete
-
-Deletes written data for the given key name.
-
-Returns `void`.
-
-###### Parameters
-
-| name | type | description |
-|------|--------|------------------------|
-| name | string | the key name to delete |
-
-###### Example
-
-```cs
-storageManager.Delete("high_score");
-// Because you cheated. Jerk.
-```
-
-## Exists
-
-Checks if data exists for a given key name.
-
-Returns `bool`.
-
-###### Parameters
-
-| name | type | description |
-|------|--------|-----------------------|
-| name | string | the key name to check |
-
-###### Example
-
-```cs
-var highScore = storageManager.Exists("high_score");
-if (!highScore)
-{
- Console.WriteLine("Couldn't find any highscore for you. Did you cheat? Jerk.");
-}
-```
-
-## Stat
-
-Returns file info for the given key name.
-
-Returns a `FileStat`.
-
-###### Parameters
-
-| name | type | description |
-|------|--------|--------------------------------|
-| name | string | the key name get file data for |
-
-###### Example
-
-```cs
-var file = storageManager.Stat("high_score");
-Console.WriteLine("File {0} is {1} in size and was last edited at {2}", file.Name, file.Size, file.LastModified);
-```
-
-## Count
-
-Returns the count of files, for iteration.
-
-Returns an `Int32`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var numFiles = storageManager.Count();
-for (int i = 0; i < numFiles; i++)
-{
- Console.WriteLine("We're at file {0}", i);
-}
-```
-
-## StatAt
-
-Returns file info for the given index when iterating over files.
-
-Returns a `FileStat`.
-
-###### Parameters
-
-| name | type | description |
-|-------|-------|--------------------------------|
-| index | Int32 | the index to get file data for |
-
-###### Example
-
-```cs
-var numFiles = storageManager.Count();
-for (int i = 0; i < numFiles; i++)
-{
- var file = storageManager.StatAt(i);
- Console.WriteLine("File is {0}", file.Name);
-}
-```
-
-## Example: Saving, Reading, Deleting, and Checking Data
-
-```cs
-var discord = new Discord.Discord(clientId, Discord.CreateFlags.Default);
-var storageManager = discord.GetStorageManager();
-
-// Create some nonsense data
-var contents = new byte[20000];
-var random = new Random();
-random.NextBytes(contents);
-
-// Write the data asynchronously
-storageManager.WriteAsync("foo", contents, res =>
-{
- // Get our list of files and iterate over it
- for (int i = 0; i < storageManager.Count(); i++)
- {
- var file = storageManager.StatAt(i);
- Console.WriteLine("file: {0} size: {1} last_modified: {2}", file.Filename, file.Size, file.LastModified);
- }
-
- // Let's read just a small chunk of data from the "foo" key
- storageManager.ReadAsyncPartial("foo", 400, 50, (result, data) =>
- {
- Console.WriteLine("partial contents of foo match {0}", Enumerable.SequenceEqual(data, new ArraySegment(contents, 400, 50)));
- });
-
- // Now let's read all of "foo"
- storageManager.ReadAsync("foo", (result, data) =>
- {
- Console.WriteLine("length of contents {0} data {1}", contents.Length, data.Length);
- Console.WriteLine("contents of foo match {0}", Enumerable.SequenceEqual(data, contents));
-
- // We just read it, but let's make sure "foo" exists
- Console.WriteLine("foo exists? {0}", storageManager.Exists("foo"));
-
- // Now delete it
- storageManager.Delete("foo");
-
- // Make sure it was deleted
- Console.WriteLine("post-delete foo exists? {0}", storageManager.Exists("foo"));
- });
-});
-```
diff --git a/docs/game_sdk/Store.md b/docs/game_sdk/Store.md
deleted file mode 100644
index 747c91862b..0000000000
--- a/docs/game_sdk/Store.md
+++ /dev/null
@@ -1,560 +0,0 @@
-# Store
-
-> info
-> Need help with the SDK? Talk to us in the [Discord Developers Server](https://discord.gg/discord-developers)!
-
-> danger
-> Selling SKUs on Discord has now been discontinued as of March 1, 2022. [Read here for more info.](https://support-dev.discord.com/hc/en-us/articles/6309018858647-Self-serve-Game-Selling-Deprecation)
-
-> danger
-> The GameSDK's Achievements, Applications, Voice, Images, Lobbies, Networking, Storage, and Store (purchases and discounts) features have been deprecated, and will be decommissioned on **May 2, 2023**. [Read more](#DOCS_CHANGE_LOG/gamesdk-feature-deprecation)
-
-If your game has DLC or offers in-app purchases, this manager is for you! The Store Manager allows you to fetch a user's entitlements, as well as being notified when a user is granted an entitlement from a purchase flow for your game.
-
-## Application Test Mode
-
-With this new Store Manager comes a new fun toggle in the Discord app itself: Application Test Mode! While in Application Test Mode, you can freely make "purchases" of SKUs tied to your application. That means you can test buying your game, buying DLC, or going through an IAP flow without any credit card charges.
-
-> info
-> You still need to have a valid payment method on file to "purchase" SKUs in Application Test Mode; it just won't be charged at checkout.
-
-To enable it, first make sure you have a payment method on file in User Settings -> Billing. Then:
-
-1. Open up the Discord app
-2. Click on the settings cog in the bottom left corner
-3. Go to Appearance -> allll the way at the bottom
-4. Toggle "Developer Mode" **on** and "Application Test Mode" **on**, and enter your application ID
-5. Exit user settings
-
-You should now see an orange bar across the top of your screen; this means it worked! The dropdown in the orange bar will show you all the available SKUs for that application; you can select one of them to go to its store page. You can also view your Library and see all the branches of your game automagically there waiting for you!
-
-If for some reason the "Install" button is greyed out, please check the following:
-
-1. Do you have a `LIVE_BUILD_ID` on that branch for this SKU? Check with `dispatch branch list `.
-2. Do you have a price tier set for this SKU? If not, pick one!
-
-Once those two conditions are met, you should be good to go! Entitlements "purchased" with this mode enabled can be revoked with the `DELETE /entitlements` HTTP endpoint, documented below.
-
-## Checking DLC Entitlements
-
-If your game has DLC, and a user has purchased that DLC, you may want to check what they should have access to when the game launches. DLC entitlements will always be returned in a `FetchEntitlements()` call, so your game can check on each startup whether or not a user should have access to a certain new zone, raid, map, etc. based on their entitlements for DLC.
-
-## Checking Consumable Entitlements
-
-The `Discord.SkuType.Consumable` type is used for entitlements that may be "consumed" by a game's own server infrastructure. That is to say that if you have in-app purchases like gem bundles, skins, etc., they will be a `Consumable` SKU type.
-
-What that means is that your game is expected to "consume" these entitlements by doing something on your game server—giving the player a level, more coins, a skin, etc.—and then telling Discord that's been done by calling the `POST /entitlements//consume`, documented below. Then, Discord will mark that entitlement as `consumed` (the `consumed` field in the returned object will be set to `true`).
-
-Entitlements to consumable SKUs are intended to signal your game's server/service/database that the user should get something in-game, and that the entitlement should be invalidated afterwards.
-
-The same consumable SKU _can_ be purchased multiple times, but we have some safeguards in place to protect against possible abuse. If you purchase a consumable SKU, you cannot purchase a second one until the first one has been consumed; in the context of normal IAP transactions, your game will be auto-consuming entitlements as soon as they're created. If some malicious folks are somehow able to generate entitlements to your SKUs, they will not be able to consume them without your token, so you'll be safe!
-
-Non-consumable SKUs can only be purchased once.
-
-## Data Models
-
-###### SKU Struct
-
-| name | type | description |
-|-------|----------|--------------------------|
-| Id | Int64 | the unique ID of the SKU |
-| Type | SkuType | what sort of SKU it is |
-| Name | string | the name of the SKU |
-| Price | SkuPrice | the price of the SKU |
-
-###### SkuType Enum
-
-| name | value | description |
-|-------------|-------|------------------------------------------------|
-| Application | 1 | SKU is a game |
-| DLC | 2 | SKU is a DLC |
-| Consumable | 3 | SKU is a consumable (in-app purchase) |
-| Bundle | 4 | SKU is a bundle (comprising the other 3 types) |
-
-###### SkuPrice Struct
-
-| name | type | description |
-|----------|--------|-----------------------------------|
-| Amount | UInt32 | the amount of money the SKU costs |
-| Currency | string | the currency the amount is in |
-
-###### Entitlement Struct
-
-| name | type | description |
-|-------|-----------------|-------------------------------------------------|
-| Id | Int64 | the unique ID of the entitlement |
-| Type | EntitlementType | the kind of entitlement it is |
-| SkuId | Int64 | the ID of the SKU to which the user is entitled |
-
-###### EntitlementType Enum
-
-| name | value | description |
-|---------------------|-------|----------------------------------------------------------------|
-| Purchase | 1 | entitlement was purchased |
-| PremiumSubscription | 2 | entitlement for a Discord Nitro subscription |
-| DeveloperGift | 3 | entitlement was gifted by a developer |
-| TestModePurchase | 4 | entitlement was purchased by a dev in application test mode |
-| FreePurchase | 5 | entitlement was granted when the SKU was free |
-| UserGift | 6 | entitlement was gifted by another user |
-| PremiumPurchase | 7 | entitlement was claimed by user for free as a Nitro Subscriber |
-
-## FetchSkus
-
-Fetches the list of SKUs for the connected application, readying them for iteration.
-
-> warn
-> Only SKUs that have a price set will be fetched. If you aren't seeing any SKUs being returned, make sure they have a price set!
-
-Returns `Discord.Result` via callback.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-storeManager.FetchSkus((result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Got skus! Now I can iterate over them!");
- }
-});
-```
-
-## CountSkus
-
-Get the number of SKUs readied by `FetchSkus()`.
-
-Returns `Int32`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-for (int i = 0; i < storeManager.CountSkus(); i++)
-{
- var sku = storeManager.GetSkuAt(i);
- Console.WriteLine("Sku is {0}", sku.Name);
-}
-```
-
-## GetSku
-
-Gets a SKU by its ID. You must call `FetchSkus()` first before being able to access SKUs in this way.
-
-Returns `Discord.Sku`.
-
-###### Parameters
-
-| name | type | description |
-|-------|-------|--------------------------|
-| skuId | Int64 | the ID of the SKU to get |
-
-###### Example
-
-```cs
-storeManager.FetchSkus((_) => {});
-var sku = storeManager.GetSku(276467180839763999);
-Console.WriteLine("Sku is {0}", sku.Name);
-```
-
-## GetSkuAt
-
-Gets a SKU by index when iterating over SKUs. You must call `FetchSkus()` first before being able to access SKUs in this way.
-
-Returns `Discord.Sku`.
-
-###### Parameters
-
-| name | type | description |
-|-------|-------|---------------------------|
-| index | Int32 | the index at which to get |
-
-###### Example
-
-```cs
-storeManager.FetchSkus((result) =>
-{
- for (int i = 0; i < storeManager.CountSkus(); i++)
- {
- var sku = storeManager.GetSkuAt(i);
- Console.WriteLine("Sku is {0}", sku.Name);
-}
-});
-```
-
-## FetchEntitlements
-
-Fetches a list of entitlements to which the user is entitled. Applications, DLC, and Bundles will always be returned. Consumables will be returned until they are consumed by the application via the HTTP endpoint.
-
-Returns `Discord.Result` via callback.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-storeManager.FetchEntitlements((result) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("Got entitlements!");
- }
-});
-```
-
-## CountEntitlements
-
-Get the number of entitlements readied by `FetchEntitlements()`. You must call `FetchEntitlements()` first before being able to access SKUs in this way.
-
-Returns `Int32`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-storeManager.FetchEntitlements((result) =>
-{
- for (int i = 0; i < storeManager.CountEntitlements(); i++)
- {
- var entitlement = storeManager.GetEntitlementAt(i);
- Console.WriteLine("Entitlement is {0}", entitlement.Name);
- }
-});
-```
-
-## GetEntitlement
-
-Gets an entitlement by its id. You must call `FetchEntitlements()` first before being able to access SKUs in this way.
-
-Returns `Discord.Entitlement`.
-
-###### Parameters
-
-| name | type | description |
-|---------------|-------|----------------------------------|
-| entitlementId | Int64 | the ID of the entitlement to get |
-
-###### Example
-
-```cs
-storeManager.FetchEntitlements((result) =>
-{
- var entitlement = storeManager.GetEntitlement(276467180839763999);
- Console.WriteLine("Entitlement is {0}", entitlement.Name);
-});
-```
-
-## GetEntitlementAt
-
-Gets an entitlement by index when iterating over a user's entitlements. You must call `FetchEntitlements()` first before being able to access SKUs in this way.
-
-Returns `Discord.Entitlement`.
-
-###### Parameters
-
-| name | type | description |
-|-------|-------|---------------------------|
-| index | Int32 | the index at which to get |
-
-###### Example
-
-```cs
-storeManager.FetchEntitlements((result) =>
-{
- for (int i = 0; i < storeManager.CountEntitlements(); i++)
- {
- var entitlement = storeManager.GetEntitlementAt(i);
- Console.WriteLine("Entitlement is {0}", entitlement.Name);
- }
-});
-```
-
-## HasSkuEntitlement
-
-Returns whether or not the user is entitled to the given SKU ID. You must call `FetchEntitlements()` first before being able to access SKUs in this way.
-
-Returns `bool`.
-
-###### Parameters
-
-| name | type | description |
-|-------|-------|----------------------------|
-| skuId | Int64 | the ID of the SKU to check |
-
-###### Example
-
-```cs
-storeManager.FetchEntitlements((result) =>
-{
- if (storeManager.HasSkuEntitlement(276467180839763999))
- {
- Console.WriteLine("User has entitlement to this SKU");
- }
- else
- {
- Console.WriteLine("How are you even running this right now...");
- }
-});
-```
-
-## StartPurchase
-
-Opens the overlay to begin the in-app purchase dialogue for the given SKU ID. You must call `FetchSkus()` first before being able to access SKUs in this way. If the user has enabled the overlay for your game, a purchase modal will appear in the overlay. Otherwise, the Discord client will be auto-focused with a purchase modal.
-
-Returns `Discord.Result` via callback.
-
-###### Parameters
-
-| name | type | description |
-|-------|-------|---------------------------------------|
-| skuId | Int64 | the ID of the SKU to begin purchasing |
-
-###### Example
-
-```cs
-storeManager.FetchSkus((result) =>
-{
- storeManager.StartPurchase(276467180839763999, (result) =>
- {
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("User is in the flow!");
- }
- });
-});
-```
-
-## OnEntitlementCreate
-
-Fires when the connected user receives a new entitlement, either through purchase or through a developer grant.
-
-###### Parameters
-
-| name | type | description |
-|-------------|---------------------|-------------------------------------------|
-| entitlement | Discord.Entitlement | the entitlement the user has been granted |
-
-## OnEntitlementDelete
-
-Fires when the connected user loses an entitlement, either by expiration, revocation, or consumption in the case of consumable entitlements.
-
-###### Parameters
-
-| name | type | description |
-|-------------|---------------------|-----------------------------------|
-| entitlement | Discord.Entitlement | the entitlement the user has lost |
-
-## HTTP APIs
-
-The following are HTTP requests, and should be handled by your game server, rather than a client. They require a token for an authorization header. This token should be the bot token of your application. To get this token, go to your application in the Dev Portal. In the left sidebar, click the `Bot` navigation item. You should then click the `Add Bot` button.
-
-After that, you can copy the token on this page and use it in your HTTP requests. The format for the authorization header should be `Authorization: Bot `.
-
-Note that parameters with a `?` after the name denote optional fields. Parameters with a `?` before their type denote nullable fields.
-
-## HTTP-Specific Data Models
-
-###### Limited Payment Data Object
-
-| name | type | description |
-|---------------|--------|--------------------------------------|
-| id | string | unique ID of the payment |
-| currency | string | the currency the payment was made in |
-| amount | int | the amount paid |
-| tax | int | the amount of tax |
-| tax_inclusive | bool | whether the amount is tax-inclusive |
-
-## Get Entitlements % GET /applications/{application.id#DOCS_GAME_SDK_GETTING_STARTED/get-set-up}/entitlements
-
-Gets entitlements for a given user. You can use this on your game backend to check entitlements of an arbitrary user, or perhaps in an administrative panel for your support team.
-
-###### Query String Params
-
-| name | type | description |
-|----------------|--------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|
-| user_id? | snowflake | the user id to look up entitlements for |
-| sku_ids? | comma-delimited set of snowflakes | (optional) the list SKU ids to check entitlements for |
-| with_payments? | [boolean](#DOCS_REFERENCE/boolean-query-strings) | returns [limited payment data](#DOCS_GAME_SDK_STORE/httpspecific-data-models-limited-payment-data-object) for each entitlement |
-| before? | snowflake | retrieve entitlements before this time |
-| after? | snowflake | retrieve entitlements after this time |
-| limit? | int | number of entitlements to return, 1-100, default 100 |
-| guild_id? | snowflake | the guild id to look up entitlements for |
-| exclude_ended? | [boolean](#DOCS_REFERENCE/boolean-query-strings) | whether or not ended entitlements should be omitted |
-
-###### Example
-
-```
-curl https://discord.com/api/v6/applications/461618159171141643/entitlements?user_id=53908232506183680&sku_ids=53908232599983680&with_payments=true&limit=1 \
--H "Authorization: Bearer " \
--H "Accept: application/json"
-
-// Returns
-
-{
- [
- {
- "user_id": "53908232506183680",
- "sku_id": "53908232599983680",
- "application_id": "461618159171141643",
- "id": "53908232506183999",
- "type": 1,
- "payment": {
- "id": "538491076055400999",
- "currency": "usd",
- "amount": 999,
- "tax": 0,
- "tax_inclusive": false
- }
- }
- ]
-}
-```
-
-## Get Entitlement % GET /applications/{application.id#DOCS_GAME_SDK_GETTING_STARTED/get-set-up}/entitlements/{entitlement.id#DOCS_GAME_SDK_STORE/data-models-entitlement-struct}
-
-Fetch an entitlement by its ID. This may be useful in confirming that a user has a given entitlement that another call or the SDK says they do.
-
-###### Query String Params
-
-| name | type | description |
-|---------------|--------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------|
-| with_payment? | [boolean](#DOCS_REFERENCE/boolean-query-strings) | returns [limited payment data](#DOCS_GAME_SDK_STORE/httpspecific-data-models-limited-payment-data-object) for each entitlement |
-
-###### Example
-
-```
-curl https://discord.com/api/v6/applications/461618159171141643/entitlements/53908232506183999?with_payment=true \
--H "Authorization: Bearer " \
--H "Accept: application/json"
-
-// Returns
-
-{
- "user_id": "53908232506183680",
- "sku_id": "53908232599983680",
- "application_id": "461618159171141643",
- "id": "53908232506183999",
- "type": 3,
- "payment": {
- "id": "538491076055400999",
- "currency": "usd",
- "amount": 999,
- "tax": 0,
- "tax_inclusive": false
- }
-}
-```
-
-## Get SKUs % GET /applications/{application.id#DOCS_GAME_SDK_GETTING_STARTED/get-set-up}/skus
-
-Get all SKUs for an application.
-
-###### Example
-
-```
-curl https://discord.com/api/v6/applications/461618159171141643/skus \
--H "Authorization: Bearer " \
--H "Accept: application/json"
-
-// Returns
-
-{
- [
- {
- "id": "53908232599983680",
- "type": 1,
- "dependent_sku_id": null,
- "application_id": "461618159171141643",
- "manifest_labels": ["461618159171111111"],
- "name": "My Awesome Test Game",
- "access_type": 1,
- "features": [1, 2, 3],
- "system_requirements": {},
- "content_ratings": {},
- "release_date": "1999-01-01",
- "legal_notice": {},
- "price_tier": 1099,
- "price": {},
- "premium": false,
- "locales": ["en-US"],
- "bundled_skus": null
- }
- ]
-}
-```
-
-## Consume SKU % POST /applications/{application.id#DOCS_GAME_SDK_GETTING_STARTED/get-set-up}/entitlements/{entitlement.id#DOCS_GAME_SDK_STORE/data-models-entitlement-struct}/consume
-
-Marks a given entitlement for the user as consumed, meaning it will no longer be returned in an entitlements check. **Ensure the user was granted whatever items the entitlement was for before consuming it!**
-
-###### Example
-
-```
-curl -X POST https://discord.com/api/v6/applications/461618159171141643/entitlements/53908232506183999/consume \
--H "Authorization: Bearer " \
--H "Accept: application/json"
-
-// Returns 204 No Content
-```
-
-## Delete Test Entitlement % DELETE /applications/{application.id#DOCS_GAME_SDK_GETTING_STARTED/get-set-up}/entitlements/{entitlement.id#DOCS_GAME_SDK_STORE/data-models-entitlement-struct}
-
-Deletes a test entitlement for an application. You can only delete entitlements that were "purchased" in developer test mode; these are entitlements of `type == TestModePurchase`. You cannot use this route to delete arbitrary entitlements that users actually purchased.
-
-###### Example
-
-```
-curl -X DELETE https://discord.com/api/v6/applications/461618159171141643/entitlements/53908232506183999 \
--H "Authorization: Bearer " \
--H "Accept: application/json"
-
-// Returns 204 No Content
-```
-
-## Create Purchase Discount % PUT /store/skus/{sku.id#DOCS_GAME_SDK_STORE/data-models-sku-struct}/discounts/{user.id#DOCS_RESOURCES_USER/user-object}
-
-Creates a discount for the given user on their next purchase of the given SKU. You should call this endpoint from your backend server just before calling [StartPurchase](#DOCS_GAME_SDK_STORE/startpurchase) for the SKU you wish to discount. The user will then see a discounted price for that SKU at time of payment. The discount is automatically consumed after successful purchase or if the TTL expires.
-
-###### Parameters
-
-| name | type | description |
-|-------------|------|----------------------------------------------------------------------------------------|
-| percent_off | int | the percentage to discount - max of 100, min of 1 |
-| ttl? | int | the time to live for the discount, in seconds - max of 3600, min of 60, default of 600 |
-
-###### Example
-
-```
-curl -X PUT https://discord.com/api/v6/store/skus/461618229171141643/discounts/53908232522183999 \
--H "Authorization: Bearer " \
--H "Accept: application/json" \
--H "Content-type: application/json" \
--d '{"percent_off": 10, "ttl": 600}'
-
-// Returns 204 No Content
-```
-
-## Delete Purchase Discount % DELETE /store/skus/{sku.id#DOCS_GAME_SDK_STORE/data-models-sku-struct}/discounts/{user.id#DOCS_RESOURCES_USER/user-object}
-
-Deletes the currently active discount on the given SKU for the given user. You **do not need** to call this after a user has made a discounted purchase; successful discounted purchases will automatically remove the discount for that user for subsequent purchases.
-
-###### Example
-
-```
-curl -X DELETE https://discord.com/api/v6/store/skus/461618229171141643/discounts/53908232522183999 \
--H "Authorization: Bearer " \
--H "Accept: application/json"
-
-// Returns 204 No Content
-```
diff --git a/docs/game_sdk/Users.md b/docs/game_sdk/Users.md
deleted file mode 100644
index 0a7a28165c..0000000000
--- a/docs/game_sdk/Users.md
+++ /dev/null
@@ -1,176 +0,0 @@
-# Users
-
-> info
-> Need help with the SDK? Talk to us in the [Discord Developers Server](https://discord.gg/discord-developers)!
-
-This manager helps retrieve basic user information for any user on Discord.
-
-## Data Models
-
-###### User Struct
-
-| name | type | description |
-|---------------|--------|-------------------------------|
-| Id | Int64 | the user's id |
-| Username | string | their name |
-| Discriminator | string | the user's unique discrim |
-| Avatar | string | the hash of the user's avatar |
-| Bot | bool | if the user is a bot user |
-
-###### UserFlag Enum
-
-| name | value | description |
-|-----------------|-------|------------------------------|
-| Partner | 2 | Discord Partner |
-| HypeSquadEvents | 4 | HypeSquad Events participant |
-| HypeSquadHouse1 | 64 | House Bravery |
-| HypeSquadHouse2 | 128 | House Brilliance |
-| HypeSquadHouse3 | 256 | House Balance |
-
-###### PremiumType Enum
-
-| name | value | description |
-|-------|-------|--------------------------|
-| None | 0 | Not a Nitro subscriber |
-| Tier1 | 1 | Nitro Classic subscriber |
-| Tier2 | 2 | Nitro subscriber |
-| Tier3 | 3 | Nitro Basic subscriber |
-
-## GetCurrentUser
-
-> info
-> Before calling this function, you'll need to wait for the [OnCurrentUserUpdate](#DOCS_GAME_SDK_USERS/oncurrentuserupdate) callback to fire after instantiating the User manager.
-
-Fetch information about the currently connected user account. If you're interested in getting more detailed information about a user—for example, their email—check out our [GetCurrentUser](#DOCS_RESOURCES_USER/get-current-user) API endpoint. You'll want to call this with an authorization header of `Bearer `, where `` is the token retrieved from a standard [OAuth2 Authorization Code Grant](#DOCS_TOPICS_OAUTH2/authorization-code-grant) flow.
-
-Returns a `Discord.User`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var user = userManager.GetCurrentUser();
-Console.WriteLine("Connected to user {0}", user.Id);
-```
-
-## GetUser
-
-Get user information for a given id.
-
-Returns a `Discord.Result` and `ref Discord.User` via callback.
-
-###### Parameters
-
-| name | type | description |
-|--------|-------|-----------------------------|
-| userId | Int64 | the id of the user to fetch |
-
-###### Example
-
-```cs
-userManager.GetUser(userId, (Discord.Result result, ref Discord.User user) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("User {0} is {1}", user.Id, user.Username);
- }
-});
-```
-
-## GetCurrentUserPremiumType
-
-Get the [PremiumType](#DOCS_GAME_SDK_USERS/data-models-premiumtype-enum) for the currently connected user.
-
-Returns `Discord.PremiumType`.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var userManager = discord.GetUserManager();
-var premiumType = userManager.GetCurrentUserPremiumType();
-switch (premiumType)
-{
- case PremiumType.None:
- Console.WriteLine("User is not a Nitro subscriber");
-
- case PremiumType.Tier1:
- Console.WriteLine("User has Nitro Classic");
-
- case PremiumType.Tier2:
- Console.WriteLine("User has Nitro");
-
- default:
- return;
-}
-```
-
-## CurrentUserHasFlag
-
-See whether or not the current user has a certain [UserFlag](#DOCS_GAME_SDK_USERS/data-models-userflag-enum) on their account.
-
-Returns `bool`.
-
-###### Parameters
-
-| name | type | description |
-|------|------------------------------------------------------------|-----------------------------------------|
-| flag | [UserFlag](#DOCS_GAME_SDK_USERS/data-models-userflag-enum) | the flag to check on the user's account |
-
-###### Example
-
-```cs
-var userManager = discord.GetUserManager();
-if (userManager.CurrentUserHasFlag(Discord.UserFlag.HypeSquadHouse1))
-{
- Console.WriteLine("User is a member of House Bravery!");
-}
-```
-
-## OnCurrentUserUpdate
-
-Fires when the `User` struct of the currently connected user changes. They may have changed their avatar, username, or something else.
-
-###### Parameters
-
-None
-
-###### Example
-
-```cs
-var userManager = discord.GetUserManager();
-// GetCurrentUser will error until this fires once.
-userManager.OnCurrentUserUpdate += () => {
- var currentUser = userManager.GetCurrentUser();
-
- Console.WriteLine(currentUser.Username);
- Console.WriteLine(currentUser.Id);
- Console.WriteLine(currentUser.Discriminator);
- Console.WriteLine(currentUser.Avatar);
-};
-```
-
-## Example: Fetching Data About a Discord User
-
-```cs
-var discord = new Discord.Discord(clientId, Discord.CreateFlags.Default);
-
-var userManager = discord.GetUserManager();
-userManager.GetUser(450795363658366976, (Discord.Result result, ref Discord.User user) =>
-{
- if (result == Discord.Result.Ok)
- {
- Console.WriteLine("user fetched: {0}", user.Username);
- }
- else
- {
- Console.WriteLine("user fetch error: {0}", result);
- }
-});
-```
diff --git a/docs/interactions/Overview.mdx b/docs/interactions/Overview.mdx
index 13b0fb0692..fc0c965ecf 100644
--- a/docs/interactions/Overview.mdx
+++ b/docs/interactions/Overview.mdx
@@ -149,7 +149,7 @@ except BadSignatureError:
In addition to ensuring your app validates security-related request headers at the time of saving your endpoint, Discord will also perform automated, routine security checks against your endpoint, including purposefully sending you invalid signatures. If you fail the validation, we will remove your interactions URL and alert you via email and System DM.
-We highly recommend checking out our [Community Resources](#DOCS_TOPICS_COMMUNITY_RESOURCES/interactions) and the libraries found there. They not only provide typing for Interactions data models, but also include decorators for API frameworks like Flask and Express to make validation easy.
+We highly recommend checking out our [Community Resources](#DOCS_DEVELOPER_TOOLS_COMMUNITY_RESOURCES/interactions) and the libraries found there. They not only provide typing for Interactions data models, but also include decorators for API frameworks like Flask and Express to make validation easy.
#### Adding an Interactions Endpoint URL
diff --git a/docs/quick_start/Getting_Started.mdx b/docs/quick_start/Getting_Started.mdx
index b22f9e9a99..d9589aba75 100644
--- a/docs/quick_start/Getting_Started.mdx
+++ b/docs/quick_start/Getting_Started.mdx
@@ -194,7 +194,7 @@ Follow the installation prompt to install your app to your user account. Once it
With your app configured and installed to your test server and account, let's take a look at the code.
> info
-> To make development a bit simpler, the app uses [discord-interactions](https://github.com/discord/discord-interactions-js), which provides types and helper functions. If you prefer to use other languages or libraries, check out the [Community Resources](#DOCS_TOPICS_COMMUNITY_RESOURCES) documentation.
+> To make development a bit simpler, the app uses [discord-interactions](https://github.com/discord/discord-interactions-js), which provides types and helper functions. If you prefer to use other languages or libraries, check out the [Community Resources](#DOCS_DEVELOPER_TOOLS_COMMUNITY_RESOURCES) documentation.
### Installing slash commands
@@ -555,7 +555,7 @@ Hopefully you learned a bit about Discord apps, how to configure them, and how t
Explore the platform features and APIs you have access to when building an app on Discord
-
+
Explore 1st party and community-built libraries and tools to speed up and simplify your development
diff --git a/docs/quick_start/Overview_of_Apps.mdx b/docs/quick_start/Overview_of_Apps.mdx
index 0a57441ffc..a876ad5261 100644
--- a/docs/quick_start/Overview_of_Apps.mdx
+++ b/docs/quick_start/Overview_of_Apps.mdx
@@ -38,7 +38,7 @@ With the right API endpoints and proper [permissions](#DOCS_TOPICS_PERMISSIONS),
Apps can use **[role connection metadata](#DOCS_RESOURCES_APPLICATION_ROLE_CONNECTION_METADATA)** to associate third-party metadata (like stats or account type) with Discord users. When server admins install the app, they'll be able to set up roles based on criteria linked to that metadata. You can explore more in the [configuring metadata for linked roles](#DOCS_TUTORIALS_CONFIGURING_APP_METADATA_FOR_LINKED_ROLES) tutorial.
-Apps can also update a user's **[rich presence](#DOCS_RICH_PRESENCE_HOW_TO)** information in Discord to make it easy for them to customize their profile with games and other activities.
+Apps can also update a user's **[rich presence](#DOCS_RICH_PRESENCE_OVERVIEW)** information in Discord to make it easy for them to customize their profile with games and other activities.
### Add premium features
@@ -97,7 +97,7 @@ Well, would you look at the time? With the basics out of the way, it's time to s
Tutorial to develop an Activity using the Embedded App SDK
-
+
Explore the Embedded App SDK and community-built library and tools to make speed up and simplify development
diff --git a/docs/resources/Application.md b/docs/resources/Application.md
index add356ebe4..398728b687 100644
--- a/docs/resources/Application.md
+++ b/docs/resources/Application.md
@@ -20,7 +20,7 @@
| privacy_policy_url? | string | URL of the app's Privacy Policy |
| owner? | partial [user](#DOCS_RESOURCES_USER/user-object) object | Partial user object for the owner of the app |
| summary *(deprecated)* | string | **deprecated and will be removed in v11.** An empty string. |
-| verify_key | string | Hex encoded key for verification in interactions and the GameSDK's [GetTicket](#DOCS_GAME_SDK_APPLICATIONS/getticket) |
+| verify_key | string | Hex encoded key for verification in interactions and the GameSDK's [GetTicket](https://github.com/discord/discord-api-docs/blob/legacy-gamesdk/docs/game_sdk/Applications.md#getticket) |
| team | ?[team](#DOCS_TOPICS_TEAMS/data-models-team-object) object | If the app belongs to a team, this will be a list of the members of that team |
| guild_id? | snowflake | Guild associated with the app. For example, a developer support server. |
| guild? | partial [guild](#DOCS_RESOURCES_GUILD/guild-object) object | Partial object of the associated guild |
diff --git a/docs/resources/Message.md b/docs/resources/Message.md
index 55f669b0ba..39ae036c04 100644
--- a/docs/resources/Message.md
+++ b/docs/resources/Message.md
@@ -109,10 +109,10 @@ Represents a message sent in a channel within Discord.
###### Message Activity Structure
-| Field | Type | Description |
-|-----------|---------|--------------------------------------------------------------------------------------------------------------------|
-| type | integer | [type of message activity](#DOCS_RESOURCES_MESSAGE/message-object-message-activity-types) |
-| party_id? | string | party_id from a [Rich Presence event](#DOCS_RICH_PRESENCE_HOW_TO/updating-presence-update-presence-payload-fields) |
+| Field | Type | Description |
+|-----------|---------|-------------------------------------------------------------------------------------------|
+| type | integer | [type of message activity](#DOCS_RESOURCES_MESSAGE/message-object-message-activity-types) |
+| party_id? | string | party_id from a Rich Presence event |
###### Message Activity Types
diff --git a/docs/rich_presence/Best_Practices.md b/docs/rich_presence/Best_Practices.md
index 958fea2b5d..82297701b9 100644
--- a/docs/rich_presence/Best_Practices.md
+++ b/docs/rich_presence/Best_Practices.md
@@ -1,38 +1,18 @@
-# Rich Presence Best Practices
+# Best Practices for Rich Presence
-> danger
-> The SDK that this documentation references, [Discord-RPC](https://github.com/discord/discord-rpc), has been deprecated in favor of our new [Discord GameSDK](#DOCS_GAME_SDK_GETTING_STARTED/). Replacement functionality for the Rich Presence SDK can be found in the [Activity Manager](#DOCS_GAME_SDK_ACTIVITIES/) of that SDK. This documentation can be referenced for education but does not entirely reflect the new SDK.
+Rich Presence lets you display actionable data in a Discord user's profile about what they're up to in your game or app. This guide is intended to show some best practices on how to make that data the best it can be.
-Rich Presence is a new feature from Discord that allows you to surface unique, interesting, and actionable data inside a Discord user’s profile when they play your game! This guide is intended to show some best practices on how to make that data the best it can be. It will include images and code samples; for full technical documentation, see our developer documentation.
-
-If you take away one thing from this guide, let it be this:
-
-> warn
-> Rich Presence data should give others a clear understanding of what someone is doing so they can decide if they want to play together or not.
-
-## Who should use Rich Presence?
-
-Rich Presence is a powerful way to integrate your game with Discord. To do it most effectively, you should think about its purpose and how well (or not) it matches with your game and your implementation. Rich Presence is designed for these three things:
-
-1. Show interesting, unique, actionable data in a user’s profile
-2. Allow friends to spectate each other’s games
-3. Join a friend’s in-game party or server directly from Discord
-
-We certainly don’t want to stifle creativity, especially for games that can use Rich Presence in an interesting way. However, keep in mind that this sort of gameplay is what it was designed for, and how players will normally interact with it.
-
-If you want to do something creative, wacky, funky, or otherwise out-there with Rich Presence for your players and aren’t sure if you can, feel free to drop us a line at [gamedevs@discord.com](mailto:gamedevs@discord.com). We’re always happy to help!
+If you don't already know about Rich Presence, read [the overview](#DOCS_RICH_PRESENCE_OVERVIEW) first.
## How should you think about the data you show?
-The data in your players’ profiles is the first thing that others on Discord will see about your game, both those familiar with it and those who have never played. It should answer two questions: can I play with my friend right now, and if not, when can I? Show data like:
+The data in your players’ profiles is the first thing that others on Discord will see about your game or app, both those familiar with it and those who have never seen it before. It should answer whether someone can play with their friend right now and show data like:
- What the player is currently doing
- How much time has elapsed or remains (if applicable)
- Their party state
- Your cool artwork!
-For a great real world example, check out [Holodrive](https://store.steampowered.com/app/370770/Holodrive/) for free on Steam!
-
## Tips
### Keep it Short
@@ -86,3 +66,41 @@ For a great real world example, check out [Holodrive](https://store.steampowered
|:-------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------:|
|  |  |
| The image is dark and unfocused. Highly-detailed images can be hard to see. | This image is bright and matches the details. Let's help! |
+
+
+## Launch Checklist
+
+Ready to launch a Rich Presence integration for your game? If so, we recommend looking over this checklist one last time to ensure that your integration is as great as it can be!
+
+#### Profile Strings
+
+- Have you made use of all available fields where appropriate?
+- Do your strings fit on their own lines without line wrapping?
+ - Did you check on the smaller profile pop out?
+- Do they clearly communicate:
+ - What the player is currently doing?
+ - If the player is in a group or playing alone?
+ - If the player is in a state where they can party up?
+
+#### Artwork
+
+- Is your artwork high resolution?
+- Are your images at least 1024x1024 pixels?
+- Is it clean, interesting, and descriptive without being too highly detailed?
+- Do you have artwork for every different state? Don't forget your default state/main menu!
+- Did you make use of tooltips and the small image where appropriate?
+
+#### Joining
+
+> info
+> Since all Activities presence data has a **Join Activity** button, Join Invites are only applicable when building with the [Game SDK](#DOCS_RICH_PRESENCE_USING_WITH_THE_GAME_SDK)
+
+- Have you successfully implemented join invites for your game if applicable?
+- Does the state of the invite properly represent the party/group in-game with regards to:
+ - Size?
+ - Open slots?
+ - Discord _and_ non-Discord users in the party?
+- Are you able to post invites to Discord without any additional in-game setup or configuration?
+- Are you properly removing data from the presence payload when someone can no longer send invites?
+ - A Join secret should not be sent if the player can't invite anyone!
+
diff --git a/docs/rich_presence/FAQ.md b/docs/rich_presence/FAQ.md
deleted file mode 100644
index baa98f1a2c..0000000000
--- a/docs/rich_presence/FAQ.md
+++ /dev/null
@@ -1,45 +0,0 @@
-# Rich Presence FAQ
-
-> danger
-> The SDK that this documentation references, [Discord-RPC](https://github.com/discord/discord-rpc), has been deprecated in favor of our new [Discord GameSDK](#DOCS_GAME_SDK_GETTING_STARTED/). Replacement functionality for the Rich Presence SDK can be found in the [Activity Manager](#DOCS_GAME_SDK_ACTIVITIES/) of that SDK. This documentation can be referenced for education but does not entirely reflect the new SDK.
-
-Below are answers to some common questions about integrating Rich Presence with your game. If you don't see your question answered here, feel free to reach out to [gamedevs@discord.com](mailto:gamedevs@discord.com) for more help.
-
-#### Q: I see "Playing MyGame", but no Rich Presence data.
-
-There's a couple things that could be going on:
-
-- If you're running two instances of the Discord client, check both!
-- Double check that your `Discord_Initialize()` function is correct.
-
-Throughout development, make sure you have your `errored()` and `disconnected()` callbacks hooked up for debugging. You can open up the console in Discord and look for errors pertaining to `SET_ACTIVITY` for more information as well.
-
-#### Q: I'm not seeing Spectate buttons on my profile.
-
-Make sure you applied for approval! If you want the Spectate button on your players' profiles, we require your integration to go through an approval process. If you have applied and have been approved and still don't see the buttons, check your Discord console for errors.
-
-#### Q: What happens if someone has more than one game running that supports Rich Presence?
-
-Due to recent changes in our infrastructure for support of multi-activities, the behavior of multiple connected Rich Presence apps has changed from what it was before. Previously, whichever application was focused would be the presence that was shown. With the recent changes, the application that connected _first_ is now displayed.
-
-However, invite functionality across multiple connected applications now works no matter which app is display on a user's profile. For example, if you are hosting a Spotify listening party, playing Game A that allows you to send Join invites, and playing Game B that allows you to send Spectate invites, you'll be able to send invites to all three simultaneously!
-
-#### Q: What if someone looking at my profile or an invite doesn't own the game?
-
-Anyone can see your profile data, whether they own the game or not. They'll only be able to interact with chat invites or profile buttons if they own the game and have launched it at least once. Otherwise, the invite/button tooltip will show "Game Not Detected".
-
-#### Q: Do join invitations allow players to select the number of open slots?
-
-Currently, the SDK does not support this. Party slot information is determined by the party data you sent in your presence payload.
-
-#### Q: Can I send images via the payload rather than uploading them to my Developer Dashboard?
-
-Yes! In addition to uploading an asset and specifying its name, you can also specify an external image URL for us to proxy. For more information, see [Activity Asset Image](#DOCS_TOPICS_GATEWAY_EVENTS/activity-object-activity-asset-image).
-
-#### Q: Can I change something in the SDK for my own purposes?
-
-Go nuts! The SDK is open source by design. If you need or want to change something for the purposes of your specific integration—like changing our JSON parser, or changing all of the variable names to the names of your pets—go ahead and tinker to your heart's content.
-
-#### Q: OK—I've got it working! Now, how do I make my integration look _awesome_?
-
-I'm happy ~~we preempted your question~~ you asked! Check out our [Rich Presence Best Practices](#DOCS_RICH_PRESENCE_BEST_PRACTICES/) guide for a rundown on how to make your integration the best that it can be!
diff --git a/docs/rich_presence/How_To.md b/docs/rich_presence/How_To.md
deleted file mode 100644
index 10d6d449da..0000000000
--- a/docs/rich_presence/How_To.md
+++ /dev/null
@@ -1,302 +0,0 @@
-# Introducing Rich Presence
-
-> danger
-> The SDK that this documentation references, [Discord-RPC](https://github.com/discord/discord-rpc), has been deprecated in favor of our new [Discord GameSDK](#DOCS_GAME_SDK_GETTING_STARTED/). Replacement functionality for the Rich Presence SDK can be found in the [Activity Manager](#DOCS_GAME_SDK_ACTIVITIES/) of that SDK. This documentation can be referenced for education but does not entirely reflect the new SDK.
-
-How easy is it for people to play your game together? With Rich Presence from Discord, it just got so easy, a ~~caveman~~ Junior Dev could do it.
-
-If you are testing a game integration with Rich Presence, other users will be able to see it. Please create a private test account and do not join any public servers while testing your integration.
-
-## So, what is it?
-
-Rich Presence allows you to leverage the totally overhauled "Now Playing" section in a Discord user's profile to help people play your game together. Rich game data—including duration, score, current boss or map, and so much more—lives inside Discord. You can spectate a friend's game directly from their profile popout, or party up via beautiful chat embeds with real-time information about open party slots and the party's in-game status. No more exchanging usernames and friend codes, or wondering if there's room for you to join. Rich Presence is a living invitation to play together, or to watch your friends kick butt.
-
-## Step 0: Get the SDK
-
-> warn
-> Please use our new Discord GameSDK. Read the documentation and get it [here](#DOCS_GAME_SDK_GETTING_STARTED/).
-
-## So, how does it work?
-
-We worked hard to make using Discord's Rich Presence system as easy as possible. All you need is our header file—what you will interact with—and our library—where we did all the hard work for you—and you are ready to roll!
-
-In the header file, you'll find six event-emitting callbacks:
-
-1. `ready()`
-2. `errored()`
-3. `disconnected()`
-4. `joinGame()`
-5. `spectateGame()`
-6. `joinRequest()`
-
-These six callbacks make up the entirety of what you need to implement. Behind the scenes, we do all the heavy lifting for you.
-
-The header file also contains the `Discord_RunCallbacks()` function. This invokes any pending callbacks from Discord on the calling thread (it's thread safe!).
-
-## Initialization
-
-The first step in implementing Rich Presence is [creating an application](#APPLICATIONS). Once you've created your application, note and save your `Client ID`. You will need this to initialize the SDK; this value will be referred to throughout this documentation as both `client_id` and `application_id`. Next, scroll down to the bottom of your application's page and hit the button that says "Enable Rich Presence". This will allow you to upload assets to your dashboard for later use.
-
-To begin, you'll register your callback functions to the six `DiscordEventHandlers` and then call `Discord_Initialize()` with your `APPLICATION_ID`. If your game is distributed via Steam, you should also pass your application's Steam ID so Discord can launch your game through Steam:
-
-###### SDK Initialization Example
-
-```c
-void InitDiscord()
-{
- DiscordEventHandlers handlers;
- memset(&handlers, 0, sizeof(handlers));
- handlers.ready = handleDiscordReady;
- handlers.errored = handleDiscordError;
- handlers.disconnected = handleDiscordDisconnected;
- handlers.joinGame = handleDiscordJoinGame;
- handlers.spectateGame = handleDiscordSpectateGame;
- handlers.joinRequest = handleDiscordJoinRequest;
-
- // Discord_Initialize(const char* applicationId, DiscordEventHandlers* handlers, int autoRegister, const char* optionalSteamId)
- Discord_Initialize("418562325121990661", &handlers, 1, "1234");
-}
-```
-
-A quick breakdown on the `Discord_Initialize()` function:
-
-- `applicationId`: your client_id/application_id
-- `handlers`: the callback functions you registered for each Discord event
-- `autoRegister`: whether or not to register an application protocol for your game on the player's computer—necessary to launch games from Discord
-- `optionalSteamId`: your game's Steam application id, if your game is distributed on Steam
-
-When you are ready to publish your integration, we recommend digging into the source code of the SDK and copying `discord_register.h`, `discord_register_win.cpp`, `discord_register_osx.m`, and `discord_register_linux.cpp` into your installation and update process. By registering your application protocols on installation and update, your players won't need to run the game before being able to interact with invites, Ask to Join, and spectating in Discord.
-
-## Shutting Down
-
-Don't leave so soon! But when you _do_ shut down your application, don't forget to call `Discord_Shutdown()`. This properly terminates the thread and allows your application to shut down cleanly.
-
-If you don't want to register all your event handlers at initialization, you can do so dynamically with `Discord_UpdateHandlers()`; this will allow you to register a new set of event handlers. Be mindful that this will delete old handlers if they are not explicitly bound to your handlers struct when calling this function.
-
-## Updating Presence
-
-> warn
-> Deprecated in favor of [Discord GameSDK ActivityManager.UpdateActivity()](#DOCS_GAME_SDK_ACTIVITIES/updateactivity)
-
-The core of Discord's Rich Presence SDK is the `Discord_UpdatePresence()` function. This is what sends your game data up to Discord to be seen and used by others. You should call `Discord_UpdatePresence()` any time something important in the presence payload changes.
-
-`Discord_UpdatePresence()` has a rate limit of one update per 15 seconds. Developers do not need to do anything to handle this rate limit. The SDK will queue up any presence updates sent in that window and send the newest one once the client is free to do so. If you are sending presence updates very frequently and wondering why you don't see your Discord presence changing, that's why!
-
-###### Update Presence Example
-
-```c
-void UpdatePresence()
-{
- char buffer[256];
- DiscordRichPresence discordPresence;
- memset(&discordPresence, 0, sizeof(discordPresence));
- discordPresence.state = "In a Group";
- sprintf(buffer, "Ranked | Mode: %d", GameEngine.GetMode());
- discordPresence.details = buffer;
- discordPresence.endTimestamp = time(0) + 5 * 60;
- discordPresence.largeImageKey = "canary-large";
- discordPresence.smallImageKey = "ptb-small";
- discordPresence.partyId = GameEngine.GetPartyId();
- discordPresence.partySize = 1;
- discordPresence.partyMax = 6;
- discordPresence.matchSecret = "4b2fdce12f639de8bfa7e3591b71a0d679d7c93f";
- discordPresence.spectateSecret = "e7eb30d2ee025ed05c71ea495f770b76454ee4e0";
- discordPresence.instance = 1;
- Discord_UpdatePresence(&discordPresence);
-}
-```
-
-###### Update Presence Payload
-
-```c
-typedef struct DiscordRichPresence {
- const char* state; /* max 128 bytes */
- const char* details; /* max 128 bytes */
- int64_t startTimestamp;
- int64_t endTimestamp;
- const char* largeImageKey; /* max 32 bytes */
- const char* largeImageText; /* max 128 bytes */
- const char* smallImageKey; /* max 32 bytes */
- const char* smallImageText; /* max 128 bytes */
- const char* partyId; /* max 128 bytes */
- int partySize;
- int partyMax;
- const char* matchSecret; /* max 128 bytes */
- const char* joinSecret; /* max 128 bytes */
- const char* spectateSecret; /* max 128 bytes */
- int8_t instance;
-} DiscordRichPresence;
-```
-
-###### Update Presence Payload Fields
-
-| parameter | type | description | example |
-|----------------|---------|------------------------------------------------------------------------------------------------------------|------------------------------------------------------------|
-| state | char\* | the user's current party status | "Looking to Play", "Playing Solo", "In a Group" |
-| details | char\* | what the player is currently doing | "Competitive - Captain's Mode", "In Queue", "Unranked PvP" |
-| startTimestamp | int64_t | epoch seconds for game start - including will show time as "elapsed" | 1507665886 |
-| endTimestamp | int64_t | epoch seconds for game end - including will show time as "remaining" | 1507665886 |
-| largeImageKey | char\* | name of the uploaded image for the large profile artwork | "default" |
-| largeImageText | char\* | tooltip for the largeImageKey | "Blade's Edge Arena", "Numbani", "Danger Zone" |
-| smallImageKey | char\* | name of the uploaded image for the small profile artwork | "rogue" |
-| smallImageText | char\* | tooltip for the smallImageKey | "Rogue - Level 100" |
-| partyId | char\* | id of the player's party, lobby, or group | "ae488379-351d-4a4f-ad32-2b9b01c91657" |
-| partySize | int | current size of the player's party, lobby, or group | 1 |
-| partyMax | int | maximum size of the player's party, lobby, or group | 5 |
-| matchSecret | char\* | (for future use) unique hashed string for a player's match | MmhuZToxMjMxMjM6cWl3amR3MWlqZA== |
-| spectateSecret | char\* | unique hashed string for Spectate button | MTIzNDV8MTIzNDV8MTMyNDU0 |
-| joinSecret | char\* | unique hashed string for chat invitations and Ask to Join | MTI4NzM0OjFpMmhuZToxMjMxMjM= |
-| instance | int8_t | (for future use) integer representing a boolean for if the player is in an instance (an in-progress match) | 1 |
-
-> info
-> Sending `endTimestamp` will **always** have the time displayed as "remaining" until the given time. Sending `startTimestamp` will show "elapsed" as long as there is no `endTimestamp` sent.
-
-Here's a handy image to see how these fields are actually displayed on a profile:
-
-
-
-| location | field name | notes |
-|----------------------------------------|----------------|-----------------------------------------------------------------------------|
-| First row below title | details | |
-| Second row below title | state | |
-| Second row below title | partySize | In parenthesis next to the `state`, first number in the format `(1 of 10)` |
-| Second row below title | partyMax | In parenthesis next to the `state`, second number in the format `(1 of 10)` |
-| Third row below title | startTimestamp | Converted to a format such as `01:33 elapsed` |
-| First button at the bottom | joinSecret | Button has the text "Ask to join" |
-| Second button at the bottom | spectateSecret | Button has the text "Spectate" |
-| Large image to the left of any content | largeImageKey | Four rows high, includes the title but not the bottom buttons |
-| Small image to the left of any content | smallImageKey | Small icon inset on the bottom right of the `largeImageKey` |
-
-Note that this layout may be subject to change without warning. This information is only provided to help those with
-impaired eyesight to understand the potential layout of this information in a user interface.
-
-## Joining
-
-> warn
-> Deprecated in favor of [Discord GameSDK ActivityManager.OnActivityJoin](#DOCS_GAME_SDK_ACTIVITIES/onactivityjoin) and [Discord GameSDK ActivityManager.OnActivityJoinRequest](#DOCS_GAME_SDK_ACTIVITIES/onactivityjoinrequest)
-
-#### Relevant Callbacks:
-
-`joinGame()`
-`joinRequest()`
-
-#### Relevant Payload Data:
-
-`partyId`
-`partySize`
-`partyMax`
-`joinSecret`
-
-When you send the relevant payload data in the `Discord_UpdatePresence()` call, your player can invite a Discord chat channel to play with them. This invite is tied to the player's party information; if their `partyId` changes, the invite will expire. If their `partySize` and `partyMax` changes, the invite will add, remove, and fill up slots dynamically.
-
-Other Discord users can click "Join" on the invitation. Their game will then launch, and the `joinGame()` callback will fire in their client with the inviting player's `joinSecret`. The client should reverse hash or otherwise unencrypt this secret and match the players together.
-
-### Ask to Join
-
-When Player B clicks the Ask to Join button on Player A's profile, the `joinRequest()` callback fires for Player A, sending the following data:
-
-###### Ask to Join Payload
-
-```c
-typedef struct DiscordJoinRequest {
- char userId[32];
- char username[344];
- char discriminator[8];
- char avatar[128];
-} DiscordJoinRequest;
-```
-
-###### Ask to Join Payload Fields
-
-| parameter | type | description |
-|---------------|-----------|-------------------------------------------------------------------------------------------------------------------------------------|
-| userId | char[24] | the userId of the player asking to join |
-| username | char[344] | the username of the player asking to join |
-| discriminator | char[8] | the discriminator of the player asking to join |
-| avatar\* | char[128] | the avatar hash of the player asking to join—see [image formatting](#DOCS_REFERENCE/image-formatting) for how to retrieve the image |
-
-> warn
-> `avatar` can be an empty string if the user has not uploaded an avatar to Discord
-
-When it fires, your game should surface this data with a Yes or No choice for Player A to accept whether or not they wish to play with Player B. Then, call `Discord_Respond()` with Player B's `userId` and the appropriate response code:
-
-###### Ask to Join Response Codes
-
-| code | value |
-|----------------------|-------|
-| DISCORD_REPLY_NO | 0 |
-| DISCORD_REPLY_YES | 1 |
-| DISCORD_REPLY_IGNORE | 2 |
-
-The Ask to Join request persists for 30 seconds after the request is received, regardless of whether you have called `Discord_RunCallbacks()` within that window. Therefore, keep these two points in mind:
-
-- Ensure you call `Discord_RunCallbacks()` as frequently as possible to ensure your game client is up to date with any data from Discord
-- If the player is in a state in which they cannot interact with an Ask to Join request—like in the middle of a match—you should not send a `joinSecret` in the presence payload
-
-## Spectating
-
-> warn
-> Deprecated in favor of [Discord GameSDK ActivityManager.OnActivitySpectate](#DOCS_GAME_SDK_ACTIVITIES/onactivityspectate)
-
-#### Relevant Callbacks:
-
-`spectateGame()`
-
-#### Relevant Payload Data:
-
-`spectateSecret`
-
-When you send the relevant payload data in the `Discord_UpdatePresence()` call, your player will gain the ability to invite a Discord chat channel to spectate their game. This invite is tied to the `matchSecret` and will expire when it changes.
-
-Other Discord users can click "Spectate" on the invitation. Their game will launch, and the `spectateGame()` callback will fire in their client with the original player's `spectateSecret`. The client should reverse hash or otherwise unencrypt this secret and spectate that player's game.
-
-## Secrets
-
-Security is of the utmost importance to us here at Discord, and we know it is for you, too. That's why we want to make sure that you properly understand `matchSecret`, `joinSecret`, and `spectateSecret` so that your game data is safe and secure over the wire.
-
-To keep security on the up and up, Discord requires that you properly hash/encode/encrypt/put-a-padlock-on-and-swallow-the-key-but-wait-then-how-would-you-open-it your secrets.
-
-Secrets are obfuscated data of your choosing. They could be match ids, player ids, lobby ids, etc. You should send us data that someone else's game client would need to join or spectate their friend. If you can't or don't want to support those actions, you don't need to send us secrets.
-
-## Rich Presence Field Requirements
-
-All fields in the `DiscordRichPresence` object are entirely optional. Anything you choose to omit simply won't be displayed; the UI will dynamically adapt from the full Rich Presence object all the way down to the basic presence view. We highly encourage you to include as many fields as you can to make your game as attractive and interactive for other players as possible. However, if you choose to be a bit more selective, here's a handy table for what each piece of Rich Presence requires:
-
-###### Rich Presence Field Requirements
-
-| Field | Custom Artwork | Spectating | Joining | Ask to Join |
-|:--------------:|:--------------:|:----------:|:-------:|:-----------:|
-| state | | | | |
-| details | | | | |
-| startTimestamp | | | | |
-| endTimestamp | | | | |
-| largeImageKey | x | | | |
-| smallImageKey | x | | | |
-| largeImageText | x | | | |
-| smallImageText | x | | | |
-| partyId | | | x | x |
-| partySize | | | x | x |
-| partyMax | | | x | x |
-| matchSecret | | | | |
-| joinSecret | | | x | x |
-| spectateSecret | | x | | |
-| instance | | | | |
-
-## Your New Developer Dashboard
-
-Included with the launch of Rich Presence is an overhaul of Discord's Developer Dashboard. We want to make Rich Presence as easy as possible to use. Our first step is helping you ditch your CDN. You're welcome.
-
-OK, well, not entirely. But! Discord _will_ host any and all artwork that you need to have the very richest of presences. Upload an image, tag it with a key—preferably one you can remember—and **bam**. It's ready for Rich Presence use. Head over to your [applications page](#APPLICATIONS) to check it out!
-
-> warn
-> **Asset keys are automatically normalized to lowercase**. Be mindful of this when referring to them in your code.
-
-## A note on testing and Game Detection
-
-If you don't see Rich Presence data in your profile while testing, make sure you don't have multiple instances of Discord running—if you do, your presence might be changing in one of those!
-
-If you're testing on your own, we recommend [downloading two separate release channels](https://discord.com/download) of the Discord desktop client. You can log into the stable, public test, and canary builds with separate credentials, making testing easier for a single developer.
-
-## So, what now?
-
-Get to coding! We can't wait to see the awesome integration you come up with. If you need some quick questions answered, look no further than our [Rich Presence FAQ](#DOCS_RICH_PRESENCE_FAQ/). If you want to know how to make your integration the best it can be, read our [Best Practices Guide](#DOCS_RICH_PRESENCE_BEST_PRACTICES/). If you're ready to release, consult our [Launch Checklist](#DOCS_RICH_PRESENCE_LAUNCH_CHECKLIST/) and make sure you haven't missed anything!
diff --git a/docs/rich_presence/Launch_Checklist.md b/docs/rich_presence/Launch_Checklist.md
deleted file mode 100644
index 8f18dee5d8..0000000000
--- a/docs/rich_presence/Launch_Checklist.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# Rich Presence Launch Checklist
-
-> danger
-> The SDK that this documentation references, [Discord-RPC](https://github.com/discord/discord-rpc), has been deprecated in favor of our new [Discord GameSDK](#DOCS_GAME_SDK_GETTING_STARTED/). Replacement functionality for the Rich Presence SDK can be found in the [Activity Manager](#DOCS_GAME_SDK_ACTIVITIES/) of that SDK. This documentation can be referenced for education but does not entirely reflect the new SDK.
-
-Ready to launch a Rich Presence integration for your game? Did you read our [Best Practices](#DOCS_RICH_PRESENCE_BEST_PRACTICES/) guide? If so, we recommend looking over this checklist one last time to ensure that your integration is as great as it can be!
-
-> warn
-> Our precompiled libraries depend on the [Visual C++ Redistributable for Visual Studio 2015](https://www.microsoft.com/en-us/download/details.aspx?id=48145). If you distribute your game on Steam, make sure to check that box in your common redistributable settings.
-
-#### Profile Strings
-
-- Have you made use of all available fields where appropriate?
-- Do your strings fit on their own lines without line wrapping?
- - Did you check on the smaller profile pop out?
-- Do they clearly communicate:
- - What the player is currently doing?
- - If the player is in a group or playing alone?
- - If the player is in a state where they can party up?
-
-#### Artwork
-
-- Is your artwork high resolution?
-- Are your images at least 1024x1024 pixels?
-- Is it clean, interesting, and descriptive without being too highly detailed?
-- Do you have artwork for every different state? Don't forget your default state/main menu!
-- Did you make use of tooltips and the small image where appropriate?
-
-#### Joining
-
-- Have you successfully implemented join invites for your game if applicable?
-- Does the state of the invite properly represent the party/group in-game with regards to:
- - Size?
- - Open slots?
- - Discord _and_ non-Discord users in the party?
-- Are you able to post invites to Discord without any additional in-game setup or configuration?
-- Are you properly removing data from the presence payload when someone can no longer send invites?
- - A `joinSecret` should not be sent if the player can't invite anyone!
-
-#### Spectating
-
-- Have you successfully implemented spectate invites for your game if applicable?
-- Is your game's spectate mode true spectating?
- - We do _not_ allow using the Spectate button as a pseudo-Join button.
-- Are you properly removing data from the presence payload when someone can no longer spectate?
- - A `spectateSecret` should not be sent if the player can't be spectated!
diff --git a/docs/rich_presence/Overview.mdx b/docs/rich_presence/Overview.mdx
new file mode 100644
index 0000000000..86469061ce
--- /dev/null
+++ b/docs/rich_presence/Overview.mdx
@@ -0,0 +1,84 @@
+# Overview of Rich Presence
+
+
+
+Rich Presence lets you display actionable data in a Discord user's profile about what they're up to in your game or app. The data you choose to display is up to you—whether it's a user's score, the duration they've been playing your game, what they're listening to on your platform, or something else.
+
+---
+
+## Choosing an SDK
+
+There are two main options when integrating Rich Presence:
+
+- The **[Embedded App SDK](#DOCS_RICH_PRESENCE_OVERVIEW/embedded-app-sdk)** should be used if you're building an [Activity](#DOCS_ACTIVITIES_OVERVIEW) in Discord.
+- The **[Game SDK](#DOCS_RICH_PRESENCE_OVERVIEW/game-sdk)** can be used if you're building an off-platform game or app and you want to integrate it into Discord.
+
+Both SDKs use similar underlying primitives (like the [`SET_ACTIVITY` RPC command](#DOCS_TOPICS_RPC/setactivity)), so a lot is the same between them. But there are a few differences, like feature compatibility, which is covered in the sections below.
+
+> info
+> Rich Presence data appears publicly on your Discord profile, so during development you should use a test account that only belongs to your private development server(s).
+
+### Embedded App SDK
+
+The [Embedded App SDK](#DOCS_DEVELOPER_TOOLS_EMBEDDED_APP_SDK) is used to build Activities, which are multiplayer games and social experiences hosted in an iframe within Discord. The SDK handles communication between Discord and the Activity and helps integrate platform features (like Rich Presence!).
+
+After a user joins an Activity, Rich Presence can be used to dynamically show data about what that user is doing or playing, as well as prompt others to join in and play along.
+
+[Read about using Rich Presence with the Embedded App SDK](#DOCS_RICH_PRESENCE_USING_WITH_THE_EMBEDDED_APP_SDK)
+
+### Game SDK
+
+The [Game SDK](#DOCS_DEVELOPER_TOOLS_GAME_SDK) makes it easier to build 3rd party games and integrate them with Discord. While many features of the Game SDK are deprecated, it can still be used for a few use cases (like integrating Rich Presence!).
+
+When integrating Rich Presence with an off-platform game, data can be shown about what a user is up to in your game. A "Join" button can also be configured to allow a user's friends to jump into their game.
+
+[Read about using Rich Presence with the Game SDK](#DOCS_RICH_PRESENCE_USING_WITH_THE_GAME_SDK)
+
+## Adding Custom Art Assets
+
+While integrating Rich Presence, you'll likely want to upload custom art assets for your app. **For all Rich Presence assets, it's highly recommended to make them 1024 x 1024**.
+
+To add custom assets for Rich Presence, navigate to your [app's settings](https://discord.com/developers/applications) and click **Rich Presence** on the left-hand sidebar. On the **Art Assets** page, there are two different types of assets you can upload.
+
+### Invite Image
+
+The Rich Presence invite image appears when [invites](#DOCS_DEVELOPER_TOOLS_GAME_SDK/sendinvite) are sent for a 3rd party game or app using the [Game SDK](#DOCS_RICH_PRESENCE_OVERVIEW/game-sdk). After uploading an invite image for your app, you can see a preview of it to the right (under "IRL Invite Image Example").
+
+> info
+> The invite image can be ignored if you're building using the [Embedded App SDK](#DOCS_RICH_PRESENCE_OVERVIEW/embedded-app-sdk). Invites sent using the Embedded App SDK's[`openInviteDialog()`](#DOCS_DEVELOPER_TOOLS_EMBEDDED_APP_SDK/openinvitedialog) use the Activity's cover art.
+
+
+
+### Assets
+
+Up to 300 custom assets can be added for your app to use when setting Rich Presence for a Discord user. These assets can be anything that help orient others to what a user is doing inside of your Activity or 3rd party game.
+
+If you need more than 300 custom assets or want to use images stored somewhere else, you can also [specify an external URL](#DOCS_TOPICS_GATEWAY_EVENTS/activity-object-activity-asset-image) as long it still has the proper dimensions and size.
+
+> info
+> For tips on choosing assets, take a look at the [Rich Presence best practices guide](#DOCS_RICH_PRESENCE_BEST_PRACTICES/have-interesting-expressive-art).
+
+When uploading Rich Presence assets, **the asset keys will automatically be changed to lowercase**. You can see this reflected in your app's settings after saving a newly-uploaded asset, and should keep it in mind when referencing any asset keys in your code.
+
+
+
+### Using the Visualizer
+
+> warn
+> The Rich Presence visualizer currently uses an outdated Discord UI, but can still be helpful as a quick-and-dirty reference for what your Rich Presence data will look like in Discord.
+
+In your app's settings, there's a Rich Presence visualizer to make it easier to see what your uploaded [assets](#DOCS_RICH_PRESENCE_OVERVIEW/assets) will look like in the context of a Discord profile. To access the visualizer, navigate to your [app's settings](https://discord.com/developers/applications) and click **Rich Presence** on the left-hand sidebar. On the **Visualizer** page, you can fill out some custom strings, party information, and select your uploaded assets to see a preview.
+
+## Start Building
+
+
+
+ Guide on using Rich Presence in the Embedded App SDK while you're building an Activity
+
+
+ Guide on using Rich Presence in the Game SDK
+
+
+ Best practices and launch checklist for when you're integrating Rich Presence with your game or app
+
+
\ No newline at end of file
diff --git a/docs/rich_presence/Using_with_the_Embedded_App_SDK.mdx b/docs/rich_presence/Using_with_the_Embedded_App_SDK.mdx
new file mode 100644
index 0000000000..a514f25269
--- /dev/null
+++ b/docs/rich_presence/Using_with_the_Embedded_App_SDK.mdx
@@ -0,0 +1,150 @@
+# Using Rich Presence with the Embedded App SDK
+
+When developing an [Activity](#DOCS_ACTIVITIES_OVERVIEW), the [Embedded App SDK](#DOCS_DEVELOPER_TOOLS_EMBEDDED_APP_SDK) makes it easy to integrate Rich Presence to display details about what a user is up to inside of your game or social experience.
+
+Rich Presence data can be thought of as an extension of your Activity—and leveling it up just a *little* makes it more interesting and relevant to the user playing your Activity (and their friends that might want to jump in and play). This guide provides an overview of the platform and technical knowledge you need to integrate Rich Presence with your existing Activity.
+
+> info
+> Not sure if you should be building with the Embedded App SDK? Read through [Choosing an SDK](#DOCS_RICH_PRESENCE_OVERVIEW/choosing-an-sdk) to understand your options when integrating Rich Presence with your app.
+
+The rest of the guide assumes you've already developed an [app](#DOCS_QUICK_START_OVERVIEW_OF_APPS) that can launch an Activity. If you aren't at that point quite yet, you should follow the guide on [building your first Activity](#DOCS_ACTIVITIES_BUILDING_AN_ACTIVITY) before continuing.
+
+## Understanding Rich Presence Data
+
+### Default Rich Presence Data
+
+By default, when a user is connected to your Activity, the app's icon will appear on their profile. If the user viewing the profile has the ability to join, a "Join Activity" button will be displayed as well.
+
+
+
+While this is okay, it's pretty limited and doesn't provide much context about what a user is actually *doing* inside of the Activity. In the following sections, we'll take a look at what richer and more actionable presence can look like.
+
+### Custom Rich Presence Data
+
+Now let's see what custom presence data can look like when a user joins your Activity. The [types for these fields](#DOCS_RICH_PRESENCE_USING_WITH_THE_EMBEDDED_APP_SDK/setactivity-fields) and [examples](#DOCS_RICH_PRESENCE_USING_WITH_THE_EMBEDDED_APP_SDK/setactivity-example) are in the sections below, but for now let's just get an idea of what we're working with:
+
+
+
+A few small things to note about the above image:
+1. `large_image` and `small_image` are both in the `assets` object, which you can see below in the [table below](#DOCS_RICH_PRESENCE_USING_WITH_THE_EMBEDDED_APP_SDK/activity-partial-object). They're labeled with the object's keys to make it more clear how they appear in a Discord profile.
+2. You can't set App Name when setting presence—it's always the name configured in your [app's settings](https://discord.com/developers/applications).
+3. Depending on the `type` you set when updating presence, the behavior and layout for some fields (particularly `small_image` and `large_text`).
+
+## Updating Presence
+
+When updating Rich Presence data using the Embedded App SDK, the only real command you need to use is **[`setActivity()`](#DOCS_DEVELOPER_TOOLS_EMBEDDED_APP_SDK/setactivity)**. Under the hood, `setActivity()` calls the RPC [`SET_ACTIVITY` command](#DOCS_TOPICS_RPC/setactivity) with the features and fields available when you're building an Activity.
+
+
+As you start exploring the Rich Presence docs, you'll start seeing the word "activity" a *lot*. The "activities" referenced in docs (like the [RPC ones](#DOCS_TOPICS_RPC/setactivity)) aren't related to the Activities you're building with the Embedded App SDK.
+
+When Rich Presence was introduced, the underlying object that contains presence data was called an "activity" (long before the Embedded App SDK), which is what the RPC [`SET_ACTIVITY` command](#DOCS_TOPICS_RPC/setactivity) is referencing. And that's *also* why the Embedded App SDK's wrapper around the RPC command is called `setActivity()` yet isn't really related to setting the state for the kind of Activity that *you're* building.
+
+We know, it's confusing ¯\\_(⊙︿⊙)_/¯ — the naming was logical at the time because it was really about the user's activity in a 3rd party game or service, but now it sorta feels like activity-ception. Understanding the nuances here aren't super important, and it's why we have guides like this one. But as they say...the more you (at least sort of) know.
+
+
+### rpc.activities.write Scope
+
+To display custom Rich Presence data for a user, your app will need to be authorized with the [`rpc.activities.write` scope](#DOCS_TOPICS_OAUTH2/shared-resources-oauth2-scopes) for that user.
+
+To request the scope, your [`authorize()`](#DOCS_DEVELOPER_TOOLS_EMBEDDED_APP_SDK/authorize) call might look something like this:
+
+
+
+> info
+> The following example only focuses on calling `authorize()`. Follow the [Building an Activity guide](#DOCS_ACTIVITIES_BUILDING_AN_ACTIVITY) for more details on topics like installing and instantiating the Embedded App SDK.
+
+```js
+// Authorize with Discord Client
+const { code } = await discordSdk.commands.authorize({
+ client_id: import.meta.env.VITE_DISCORD_CLIENT_ID,
+ response_type: "code",
+ state: "",
+ prompt: "none",
+ scope: [
+ "identify",
+ "rpc.activities.write"
+ ],
+});
+```
+
+
+### setActivity Fields
+
+When calling [`setActivity()`](#DOCS_DEVELOPER_TOOLS_EMBEDDED_APP_SDK/setactivity), you are expected to pass a partial [activity object](#DOCS_TOPICS_GATEWAY_EVENTS/activity-object-activity-structure).
+
+Below is a table with many of the available fields for the activity partial. Some were left out since they don't have an effect for Activities.
+
+#### Activity partial object
+
+> info
+> All of the fields on the partial object are optional and nullable
+
+| field | type | description |
+|------------|--------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------|
+| type | integer | [Activity](#DOCS_TOPICS_GATEWAY_EVENTS/activity-object-activity-types) type, which determines the header text for the Rich Presence data |
+| state | string | User's current party status |
+| details | string | What the player is currently doing in your Activity |
+| timestamps | [timestamps](#DOCS_TOPICS_GATEWAY_EVENTS/activity-object-activity-timestamps) object | Unix timestamps to display stand and/or end times |
+| assets | [assets](#DOCS_TOPICS_GATEWAY_EVENTS/activity-object-activity-assets) object | Images used for the Rich Presence data (and their hover texts) |
+| party | [party](#DOCS_TOPICS_GATEWAY_EVENTS/activity-object-activity-party) object | Information for the current party of the player |
+
+### setActivity Example
+
+Now let's take a look at more of a real example. Take a look at the Rich Presence data below that is for an Activity:
+
+
+
+To create this sort of Rich Presence, here is what the `setActivity()` code would look like:
+
+
+
+> info
+> The following example only focuses on using `setActivity()`. Follow the [Building an Activity guide](#DOCS_ACTIVITIES_BUILDING_AN_ACTIVITY) for more details on topics like instantiating the Embedded App SDK and authenticating users.
+```js
+await discordSdk.commands.setActivity({
+ activity: {
+ type: 0,
+ state: 'Traveling with a Group',
+ details: 'in Mainframe Map',
+ assets: {
+ large_image: 'main-game-image',
+ large_text: 'in a group',
+ small_image: 'map-mainframe',
+ small_text: 'in Mainframe'
+ },
+ timestamps: {
+ start: 1723137832
+ },
+ party: {
+ size: [2,4]
+ }
+ }
+});
+```
+
+
+## Using External Custom Assets
+
+Typically when building an Activity, you need to be aware of the proxy and [how to use external resources](#DOCS_ACTIVITIES_DEVELOPMENT_GUIDES/using-external-resources). However, lucikly for you (and the writer of this guide), image URLs in fields for features like Rich Presence don't need to jump through any extra hoops.
+
+As mentioned in the [Rich Presence overview](#DOCS_RICH_PRESENCE_OVERVIEW/assets), you have more than 300 custom assets or if you want to use your stored images from somewhere else, you can specify an external URL for `large_image` or `small_image` within the `assets` object.
+
+
+
+> info
+> The following example only focuses on using `setActivity()`. Follow the [Building an Activity guide](#DOCS_ACTIVITIES_BUILDING_AN_ACTIVITY) for more details on topics like instantiating the Embedded App SDK and authenticating users.
+```js
+await discordSdk.commands.setActivity({
+ activity: {
+ type: 2,
+ state: 'Broken Hearts and Code (club edit)',
+ details: 'DJ Wump',
+ assets: {
+ large_image: 'https://example.com/album-covers/dj-wump/broken-code-and-hearts-club-edit.jpg',
+ large_text: 'Listening to a track',
+ }
+ }
+});
+```
+
+
diff --git a/docs/rich_presence/Using_with_the_Game_SDK.mdx b/docs/rich_presence/Using_with_the_Game_SDK.mdx
new file mode 100644
index 0000000000..62c6180133
--- /dev/null
+++ b/docs/rich_presence/Using_with_the_Game_SDK.mdx
@@ -0,0 +1,222 @@
+# Using Rich Presence with the Game SDK
+
+The [Game SDK](#DOCS_DEVELOPER_TOOLS_GAME_SDK) helps you build 3rd party games and integrate them with Discord. One of its specialties is making it easy to bring your game's data to Discord using [Rich Presence](#DOCS_RICH_PRESENCE_OVERVIEW), which this guide will cover.
+
+Before we dig in, make sure you've gone through the guide on [Getting Started with the Game SDK](#DOCS_DEVELOPER_TOOLS_GAME_SDK/getting-started). This guide expects that you've already [downloaded the SDK](#DOCS_DEVELOPER_TOOLS_GAME_SDK/step-1-get-the-sdk), [configured your app](#DOCS_DEVELOPER_TOOLS_GAME_SDK/step-2-create-your-app), and [gotten up and running with a basic example](#DOCS_DEVELOPER_TOOLS_GAME_SDK/step-3-start-coding).
+
+> info
+> Not sure if you should be building with the Game SDK? Read through [Choosing an SDK](#DOCS_RICH_PRESENCE_OVERVIEW/choosing-an-sdk) to understand your options when integrating Rich Presence.
+
+## Understanding Rich Presence Data
+
+Before we dig in, it's helpful to understand what Rich Presence data you can set when updating a user's presence data. We'll explain the specific fields below, but for now let's just take a look at what we're working with:
+
+
+
+
+| location | field name | notes |
+|----------------------------------------|----------------|-----------------------------------------------------------------------------|
+| First row below title | details | |
+| Second row below title | state | |
+| Second row below title | partySize | In parenthesis next to the `state`, first number in the format `(1 of 10)` |
+| Second row below title | partyMax | In parenthesis next to the `state`, second number in the format `(1 of 10)` |
+| Third row below title | startTimestamp | Converted to a format such as `01:33 elapsed` |
+| First button at the bottom | joinSecret | Button has the text "Ask to join" |
+| Second button at the bottom | spectateSecret | Button has the text "Spectate" |
+| Large image to the left of any content | largeImageKey | Four rows high, includes the title but not the bottom buttons |
+| Small image to the left of any content | smallImageKey | Small icon inset on the bottom right of the `largeImageKey` |
+
+Note that this layout may be subject to change without warning. This information is only provided to help those with
+impaired eyesight to understand the potential layout of this information in a user interface.
+
+
+> info
+> For tips on designing Rich Presence, take a look at the [Rich Presence best practices guide](#DOCS_RICH_PRESENCE_BEST_PRACTICES).
+
+## Activities Manager
+
+As you likely learned when setting up your app, the Game SDK has a handful of specialized [manager classes](#DOCS_DEVELOPER_TOOLS_GAME_SDK/managers). The **[`ActivitiesManager`](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activities)** is responsible for integrating Rich Presence and sending invites, so that's where we'll spend our focus in this guide.
+
+Like other Game SDK managers, the `ActivitiesManager` class has a handful of [functions](#DOCS_DEVELOPER_TOOLS_GAME_SDK/functions) and [events](#DOCS_DEVELOPER_TOOLS_GAME_SDK/functions) that are used when building Rich Presence support. We'll touch on the ones important to presence below.
+
+### Fetching Activity Manager
+
+In your code, you'll need to fetch the `ActivityManager` to call its functions and listen to events. In your code, you can call the `GetActivityManager()` function:
+
+```cs
+var activityManager = discord.GetActivityManager();
+```
+
+## Updating Presence
+
+The most important function when integrating Rich Presence using the Game SDK will be [`UpdateActivity()`](#DOCS_DEVELOPER_TOOLS_GAME_SDK/updateactivity). This is how you will send your game data to Discord to update a user's presence data. You should call `UpdateActivity()` any time something important in the presence payload changes.
+
+### UpdateActivity Fields
+
+When calling `UpdateActivity()`, you'll be expected to pass the [activity](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activity-struct) fields besides your `ApplicationId` and `Name` (which are both read-only).
+
+#### Partial Activity Struct
+
+Below are the fields we'll be paying attention to as we're passing presence data for a user.
+
+> info
+> All fields are optional and nullable
+
+| Name | Type | Description |
+|------------|--------------------------------------------------------------------------------|-----------------------------------------------------------------|
+| State | string | the player's current party status |
+| Details | string | what the player is currently doing |
+| Timestamps | [ActivityTimestamps](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activitytimestamps-struct) | helps create elapsed/remaining timestamps on a player's profile |
+| Assets | [ActivityAssets](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activityassets-struct) | assets to display on the player's profile |
+| Party | [ActivityParty](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activityparty-struct) | information about the player's party |
+| Secrets | [ActivitySecrets](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activitysecrets-struct) | secret passwords for joining the player's game |
+| Instance | bool | whether this activity is an instanced context, like a match |
+
+### UpdateActivity Example
+
+Now let's take a look at a code example for updating presence data.
+
+> info
+> All of the code samples in this guide are in C#, but there are some similar examples in other languages [on GitHub](https://github.com/msciotti/discord-game-sdk-test-apps).
+
+Our code sample in this section is based on the data from the example from before:
+
+
+
+This example contains two buttons—the **Ask to Join** button and the **Spectate** button. The **Ask to Join** button will be covered more in the following sections, but if you don't want it included, you can remove the `Party` and `Secret` fields.
+
+> warn
+> While the example shows a **Spectating** button, support for spectating was removed and you can ignore references to it.
+
+
+
+> info
+> The following example only focuses on using `UpdateActivity()`. You can read the [Getting Started](#DOCS_DEVELOPER_TOOLS_GAME_SDK/getting-started) and [Using the SDK](#DOCS_DEVELOPER_TOOLS_GAME_SDK/using-the-sdk) sections for more general information about using the Game SDK.
+
+```cs
+var activity = new Discord.Activity
+{
+ State = "In Group",
+ Details = "In 3v3 Arena | 0-2 | Bo5",
+ Timestamps =
+ {
+ Start = 1723218695,
+ },
+ Assets =
+ {
+ LargeImage = "map-woods", // using asset from app's settings
+ LargeText = "Playing in the Misty Woods",
+ SmallImage = "https://example.com/battlerite/users/example-user.jpg", // you can also use URLs
+ SmallText = "Example User",
+ },
+ Party =
+ {
+ Id = "party-abc123",
+ Size = {
+ CurrentSize = 3,
+ MaxSize = 3,
+ },
+ },
+ Secrets =
+ {
+ Join = "foo joinSecret",
+ },
+ Instance = true,
+
+};
+
+activityManager.UpdateActivity(activity, (result) =>
+{
+ if (result == Discord.Result.Ok)
+ {
+ Console.WriteLine("Success!");
+ }
+ else
+ {
+ Console.WriteLine("Failed");
+ }
+});
+```
+
+
+## Asking to Join
+
+In the example above, there was an **Ask to Join** button that a user could click to ask to join a game match directly from Discord.
+
+### Adding the Ask to Join Button
+
+To get the **Ask to Join** button to appear under the presence data for a 3rd party game, you should send along a few fields: `ActivityParty.Id`, `ActivityParty.Size.CurrentSize`, `ActivityParty.Size.MaxSize`, and `ActivitySecrets.Join`.
+
+To see what you need for each Rich Presence feature, you can view the [Activity Action Field Requirements](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activity-action-field-requirements) table.
+
+### Handling Ask to Join
+
+To listen for when someone clicks the button, you'll use the [`OnActivityJoinRequest` event](#DOCS_DEVELOPER_TOOLS_GAME_SDK/onactivityjoinrequest). This will include a [user](#DOCS_DEVELOPER_TOOLS_GAME_SDK/user-struct) for the individual that clicked the button.
+
+As an example, let's say we updated Player A's presence data, and Player B found the **Ask to Join** button on their profile and proceeded to click it. At that point, your app will receive an `OnActivityJoinRequest`. Your game should surface this to Player A to confirm they wish to play with Player B.
+
+After you confirm that Player A is game, you will call [`SendRequestReply`](#DOCS_DEVELOPER_TOOLS_GAME_SDK/sendrequestreply) with Player B's `userId` and a `reply` field with an [`ActivityJoinRequestReply` value](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activityjoinrequestreply-enum).
+
+
+
+```cs
+activityManager.OnActivityJoinRequest += user =>
+{
+ Console.WriteLine("Join request from: {0}", user.Id);
+ activityManager.SendRequestReply(user.Id, Discord.ActivityJoinRequestReply.Yes, (res) =>
+ {
+ if (res == Discord.Result.Ok)
+ {
+ Console.WriteLine("Responded successfully");
+ }
+ });
+}
+```
+
+
+The Ask to Join request persists for 30 seconds after the request is received. Therefore, keep these two points in mind:
+- Ensure you call [`RunCallbacks()`](#DOCS_DEVELOPER_TOOLS_GAME_SDK/runcallbacks) as frequently as possible to ensure your game client is up to date with any data from Discord
+- If the player is in a state in which they cannot interact with an Ask to Join request—like in the middle of a match—you should not send `ActivitySecrets.Join` in the presence payload
+
+## Secrets
+
+Security is of the utmost importance to us here at Discord, and we know it is for you, too. That's why we want to make sure that you properly understand `ActivitySecrets.Join` so that your game data is safe and secure over the wire.
+
+To keep security on the up and up, Discord requires that you properly hash/encode/encrypt/put-a-padlock-on-and-swallow-the-key-but-wait-then-how-would-you-open-it your secrets.
+
+Secrets are obfuscated data of your choosing. They could be match ids, player ids, lobby ids, etc. You should send us data that someone else's game client would need to join their friend. If you can't or don't want to support those actions, you don't need to send us secrets.
+
+## FAQ
+
+Below are answers to some common questions about integrating Rich Presence with your 3rd party game.
+
+#### Q: I see "Playing MyGame", but no Rich Presence data.
+
+There's a couple things that could be going on:
+
+- If you're running two instances of the Discord client, check both!
+- Double check that your `Discord_Initialize()` function is correct.
+
+Throughout development, make sure you have your `errored()` and `disconnected()` callbacks hooked up for debugging. You can open up the console in Discord and look for errors pertaining to `SET_ACTIVITY` for more information as well.
+
+#### Q: What happens if someone has more than one game running that supports Rich Presence?
+
+The application that connected _first_ is displayed.
+
+However, invite functionality across multiple connected applications now works no matter which app is display on a user's profile. For example, if you are hosting a Spotify listening party, playing Game A that allows you to send Join invites, and playing Game B that allows you to send Spectate invites, you'll be able to send invites to all three simultaneously!
+
+#### Q: What if someone looking at my profile or an invite doesn't own the game?
+
+Anyone can see your profile data, whether they own the game or not. They'll only be able to interact with chat invites or profile buttons if they own the game and have launched it at least once. Otherwise, the invite/button tooltip will show "Game Not Detected".
+
+#### Q: Do join invitations allow players to select the number of open slots?
+
+Currently, the SDK does not support this. Party slot information is determined by the party data you sent in your presence payload.
+
+#### Q: Can I send images via the payload rather than uploading them to my app's settings?
+
+Yes! In addition to uploading an asset and specifying its name, you can also specify an external image URL for us to proxy. For more information, see [Activity Asset Image](#DOCS_TOPICS_GATEWAY_EVENTS/activity-object-activity-asset-image).
+
+#### Q: OK—I've got it working! Now, how do I make my integration look _awesome_?
+
+I'm happy ~~we preempted your question~~ you asked! Check out our [Rich Presence Best Practices](#DOCS_RICH_PRESENCE_BEST_PRACTICES/) guide for a rundown on how to make your integration the best that it can be!
diff --git a/docs/topics/Gateway.md b/docs/topics/Gateway.md
index 6f1523651e..f819926954 100644
--- a/docs/topics/Gateway.md
+++ b/docs/topics/Gateway.md
@@ -5,7 +5,7 @@ The Gateway API lets apps open secure WebSocket connections with Discord to rece
> info
> In *most* cases, performing REST operations on Discord resources can be done using the [HTTP API](#DOCS_REFERENCE/http-api) rather than the Gateway API.
-The Gateway is Discord's form of real-time communication used by clients (including apps), so there are nuances and data passed that simply isn't relevant to apps. Interacting with the Gateway can be tricky, but there are [community-built libraries](#DOCS_TOPICS_COMMUNITY_RESOURCES/libraries) with built-in support that simplify the most complicated bits and pieces. If you're planning on writing a custom implementation, be sure to read the following documentation in its entirety so you understand the sacred secrets of the Gateway (or at least those that matter for apps).
+The Gateway is Discord's form of real-time communication used by clients (including apps), so there are nuances and data passed that simply isn't relevant to apps. Interacting with the Gateway can be tricky, but there are [community-built libraries](#DOCS_DEVELOPER_TOOLS_COMMUNITY_RESOURCES/libraries) with built-in support that simplify the most complicated bits and pieces. If you're planning on writing a custom implementation, be sure to read the following documentation in its entirety so you understand the sacred secrets of the Gateway (or at least those that matter for apps).
## Gateway Events
diff --git a/docs/topics/OAuth2.md b/docs/topics/OAuth2.md
index ff693bba6a..444a838b14 100644
--- a/docs/topics/OAuth2.md
+++ b/docs/topics/OAuth2.md
@@ -24,7 +24,7 @@ These are a list of all the OAuth2 scopes that Discord supports. Some scopes req
| Name | Description |
|------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| activities.read | allows your app to fetch data from a user's "Now Playing/Recently Played" list — not currently available for apps |
-| activities.write | allows your app to update a user's activity - not currently available for apps (NOT REQUIRED FOR [GAMESDK ACTIVITY MANAGER](#DOCS_GAME_SDK_ACTIVITIES/)) |
+| activities.write | allows your app to update a user's activity - not currently available for apps (NOT REQUIRED FOR [GAMESDK ACTIVITY MANAGER](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activities)) |
| applications.builds.read | allows your app to read build data for a user's applications |
| applications.builds.upload | allows your app to upload/update builds for a user's applications - requires Discord approval |
| applications.commands | allows your app to add [commands](#DOCS_INTERACTIONS_APPLICATION_COMMANDS/) to a guild - included by default with the `bot` scope |
diff --git a/docs/topics/RPC.md b/docs/topics/RPC.md
index b59fe0e5e0..5b4da72f1d 100644
--- a/docs/topics/RPC.md
+++ b/docs/topics/RPC.md
@@ -1535,9 +1535,9 @@ No arguments
###### Activity Join Dispatch Data Structure
-| Field | Type | Description |
-|--------|--------|-----------------------------------------------------------------------------------------------------------------------|
-| secret | string | the [`join_secret`](#DOCS_RICH_PRESENCE_HOW_TO/updating-presence-update-presence-payload-fields) for the given invite |
+| Field | Type | Description |
+|--------|--------|-------------------------------------------------------------------------------------------------|
+| secret | string | the [`join_secret`](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activitysecrets-struct) for the given invite |
###### Example Activity Join Dispatch Payload
@@ -1557,9 +1557,9 @@ No arguments
###### Activity Spectate Dispatch Data Structure
-| Field | Type | Description |
-|--------|--------|---------------------------------------------------------------------------------------------------------------------------|
-| secret | string | the [`spectate_secret`](#DOCS_RICH_PRESENCE_HOW_TO/updating-presence-update-presence-payload-fields) for the given invite |
+| Field | Type | Description |
+|--------|--------|-----------------------------------------------------------------------------------------------------|
+| secret | string | the [`spectate_secret`](#DOCS_DEVELOPER_TOOLS_GAME_SDK/activitysecrets-struct) for the given invite |
###### Example Activity Spectate Dispatch Payload
diff --git a/docs/tutorials/Upgrading_to_Application_Commands.md b/docs/tutorials/Upgrading_to_Application_Commands.md
index 55504dfcef..87b40f4270 100644
--- a/docs/tutorials/Upgrading_to_Application_Commands.md
+++ b/docs/tutorials/Upgrading_to_Application_Commands.md
@@ -144,7 +144,7 @@ However, before adding your URL to your app settings, your endpoint must be set
2. **Verifying request signatures**: To ensure that requests are coming from Discord, your endpoint must verify each request using the included headers, specifically `X-Signature-Ed25519` and `X-Signature-Timestamp`. If the signature fails validating, your app should return a `401` response. More information and example code can be found in the [Security and Authorization documentation](#DOCS_INTERACTIONS_OVERVIEW/setting-up-an-endpoint-validating-security-request-headers).
> info
-> Many libraries on the [Community Resources page](#DOCS_TOPICS_COMMUNITY_RESOURCES/interactions) simplify verification and interaction request handling by exporting reusable functions and/or handling it automatically.
+> Many libraries on the [Community Resources page](#DOCS_DEVELOPER_TOOLS_COMMUNITY_RESOURCES/interactions) simplify verification and interaction request handling by exporting reusable functions and/or handling it automatically.
After your URL is set up to handle signature verification and `PING` requests, you can add your Interaction Endpoint URL by navigating to your app settings from the [developer portal](https://discord.com/developers/applications). On the **General Information** page, you’ll see a field for your **Interactions Endpoint URL**.
diff --git a/images/activities-presence-example.png b/images/activities-presence-example.png
new file mode 100644
index 0000000000..8f9523992d
Binary files /dev/null and b/images/activities-presence-example.png differ
diff --git a/images/annotated-presence-data-activities.png b/images/annotated-presence-data-activities.png
new file mode 100644
index 0000000000..4e28adc940
Binary files /dev/null and b/images/annotated-presence-data-activities.png differ
diff --git a/images/default-presence-activities.png b/images/default-presence-activities.png
new file mode 100644
index 0000000000..595508a80f
Binary files /dev/null and b/images/default-presence-activities.png differ
diff --git a/images/game-sdk-presence-example.png b/images/game-sdk-presence-example.png
new file mode 100644
index 0000000000..066af7ff35
Binary files /dev/null and b/images/game-sdk-presence-example.png differ
diff --git a/images/rich-presence-asset-images.png b/images/rich-presence-asset-images.png
new file mode 100644
index 0000000000..f859558940
Binary files /dev/null and b/images/rich-presence-asset-images.png differ
diff --git a/images/rich-presence-examples.png b/images/rich-presence-examples.png
new file mode 100644
index 0000000000..2477b56b62
Binary files /dev/null and b/images/rich-presence-examples.png differ
diff --git a/images/rich-presence-invite-image.png b/images/rich-presence-invite-image.png
new file mode 100644
index 0000000000..03e18f46c8
Binary files /dev/null and b/images/rich-presence-invite-image.png differ