Skip to content

Commit

Permalink
add support for buttons and overlay guild and activity invites
Browse files Browse the repository at this point in the history
  • Loading branch information
p0358 committed Mar 11, 2022
1 parent e659923 commit a68bb5c
Show file tree
Hide file tree
Showing 5 changed files with 201 additions and 11 deletions.
57 changes: 53 additions & 4 deletions examples/send-presence/send-presence.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@
static const char* APPLICATION_ID = "345229890980937739";
static int FrustrationLevel = 0;
static int64_t StartTime;
static int SendPresence = 1;
static char SendPresence = 1;
static char SendButtons = 0;

static int prompt(char* line, size_t size)
{
Expand Down Expand Up @@ -52,6 +53,15 @@ static void updateDiscordPresence()
discordPresence.joinSecret = "join";
discordPresence.spectateSecret = "look";
discordPresence.instance = 0;

DiscordButton buttons[] = {
{.label = "Test", .url = "https://example.com"},
{.label = "Test 2", .url = "https://discord.gg/fortnite"},
};

if (SendButtons)
discordPresence.buttons = buttons;

Discord_UpdatePresence(&discordPresence);
}
else {
Expand Down Expand Up @@ -153,6 +163,12 @@ static void gameLoop()
continue;
}

if (line[0] == 'y') {
printf("Reinit Discord.\n");
discordInit();
continue;
}

if (line[0] == 'c') {
if (SendPresence) {
printf("Clearing presence information.\n");
Expand All @@ -166,11 +182,44 @@ static void gameLoop()
continue;
}

if (line[0] == 'y') {
printf("Reinit Discord.\n");
discordInit();
if (line[0] == 'b') {
if (SendButtons) {
printf("Removing buttons.\n");
SendButtons = 0;
}
else {
printf("Adding buttons.\n");
SendButtons = 1;
}
updateDiscordPresence();
continue;
}

if (line[0] == 'i' && line[1]) {
if (line[1] == 'a') {
printf("Opening activity invite (type 1).\n");
Discord_OpenActivityInvite(1);
continue;
}

if (line[1] == '2') { // does not seem to work
printf("Opening activity invite (type 2).\n");
Discord_OpenActivityInvite(2);
continue;
}

if (line[1] == '0') { // does not seem to work either...
printf("Opening activity invite (type 0).\n");
Discord_OpenActivityInvite(0);
continue;
}

if (line[1] == 'g') {
printf("Opening guild invite.\n");
Discord_OpenGuildInvite("fortnite");
continue;
}
}

if (time(NULL) & 1) {
printf("I don't understand that.\n");
Expand Down
12 changes: 12 additions & 0 deletions include/discord_rpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@
extern "C" {
#endif

typedef struct DiscordButton {
const char* label;
const char* url;
} DiscordButton;

typedef struct DiscordRichPresence {
const char* state; /* max 128 bytes */
const char* details; /* max 128 bytes */
Expand All @@ -40,6 +45,7 @@ typedef struct DiscordRichPresence {
const char* joinSecret; /* max 128 bytes */
const char* spectateSecret; /* max 128 bytes */
int8_t instance;
const DiscordButton* buttons;
} DiscordRichPresence;

typedef struct DiscordUser {
Expand All @@ -64,6 +70,9 @@ typedef struct DiscordEventHandlers {
#define DISCORD_PARTY_PRIVATE 0
#define DISCORD_PARTY_PUBLIC 1

#define DISCORD_ACTIVITY_ACTION_TYPE_JOIN 1
#define DISCORD_ACTIVITY_ACTION_TYPE_SPECTATE 2

DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
DiscordEventHandlers* handlers,
int autoRegister,
Expand All @@ -83,6 +92,9 @@ DISCORD_EXPORT void Discord_ClearPresence(void);

DISCORD_EXPORT void Discord_Respond(const char* userid, /* DISCORD_REPLY_ */ int reply);

DISCORD_EXPORT void Discord_OpenActivityInvite(/* DISCORD_ACTIVITY_ACTION_TYPE_ */ int8_t type);
DISCORD_EXPORT void Discord_OpenGuildInvite(const char* code);

DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* handlers);

#ifdef __cplusplus
Expand Down
30 changes: 30 additions & 0 deletions src/discord_rpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,36 @@ extern "C" DISCORD_EXPORT void Discord_Respond(const char* userId, /* DISCORD_RE
}
}

extern "C" DISCORD_EXPORT void Discord_OpenActivityInvite(int8_t type)
{
// if we are not connected, let's not batch up stale messages for later
if (!Connection || !Connection->IsOpen()) {
return;
}
auto qmessage = SendQueue.GetNextAddMessage();
if (qmessage) {
qmessage->length = JsonWriteOpenOverlayActivityInvite(
qmessage->buffer, sizeof(qmessage->buffer), type, Nonce++, Pid);
SendQueue.CommitAdd();
SignalIOActivity();
}
}

extern "C" DISCORD_EXPORT void Discord_OpenGuildInvite(const char* code)
{
// if we are not connected, let's not batch up stale messages for later
if (!Connection || !Connection->IsOpen()) {
return;
}
auto qmessage = SendQueue.GetNextAddMessage();
if (qmessage) {
qmessage->length =
JsonWriteOpenOverlayGuildInvite(qmessage->buffer, sizeof(qmessage->buffer), code, Nonce++, Pid);
SendQueue.CommitAdd();
SignalIOActivity();
}
}

extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void)
{
// Note on some weirdness: internally we might connect, get other signals, disconnect any number
Expand Down
101 changes: 94 additions & 7 deletions src/serialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,17 +149,41 @@ size_t JsonWriteRichPresenceObj(char* dest,
}
}

if ((presence->matchSecret && presence->matchSecret[0]) ||
(presence->joinSecret && presence->joinSecret[0]) ||
(presence->spectateSecret && presence->spectateSecret[0])) {
WriteObject secrets(writer, "secrets");
WriteOptionalString(writer, "match", presence->matchSecret);
WriteOptionalString(writer, "join", presence->joinSecret);
WriteOptionalString(writer, "spectate", presence->spectateSecret);
// Send secrets only when buttons aren't set
if (!presence->buttons) {
if ((presence->matchSecret && presence->matchSecret[0]) ||
(presence->joinSecret && presence->joinSecret[0]) ||
(presence->spectateSecret && presence->spectateSecret[0])) {
WriteObject secrets(writer, "secrets");
WriteOptionalString(writer, "match", presence->matchSecret);
WriteOptionalString(writer, "join", presence->joinSecret);
WriteOptionalString(writer, "spectate", presence->spectateSecret);
}
}

writer.Key("instance");
writer.Bool(presence->instance != 0);

if (presence->buttons) {
const auto btns = presence->buttons;
WriteArray buttons(writer, "buttons");

if (btns[0].label[0]) {
WriteObject button0(writer);
WriteKey(writer, "url");
writer.String(btns[0].url);
WriteKey(writer, "label");
writer.String(btns[0].label);
}

if (btns[1].label[0]) {
WriteObject button1(writer);
WriteKey(writer, "url");
writer.String(btns[1].url);
WriteKey(writer, "label");
writer.String(btns[1].label);
}
}
}
}
}
Expand Down Expand Up @@ -248,3 +272,66 @@ size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int rep

return writer.Size();
}

size_t JsonWriteOpenOverlayActivityInvite(char* dest,
size_t maxLen,
int8_t type,
int nonce,
int pid)
{
JsonWriter writer(dest, maxLen);

{
WriteObject obj(writer);

WriteKey(writer, "cmd");
writer.String("OPEN_OVERLAY_ACTIVITY_INVITE");

WriteKey(writer, "args");
{
WriteObject args(writer);

WriteKey(writer, "type");
writer.Int(type);

// just to make sure?
WriteKey(writer, "pid");
writer.Int(pid);
}

JsonWriteNonce(writer, nonce);
}

return writer.Size();
}

size_t JsonWriteOpenOverlayGuildInvite(char* dest,
size_t maxLen,
const char* code,
int nonce,
int pid)
{
JsonWriter writer(dest, maxLen);

{
WriteObject obj(writer);

WriteKey(writer, "cmd");
writer.String("OPEN_OVERLAY_GUILD_INVITE");

WriteKey(writer, "args");
{
WriteObject args(writer);

WriteKey(writer, "code");
writer.String(code);

WriteKey(writer, "pid");
writer.Int(pid);
}

JsonWriteNonce(writer, nonce);
}

return writer.Size();
}
12 changes: 12 additions & 0 deletions src/serialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,18 @@ size_t JsonWriteUnsubscribeCommand(char* dest, size_t maxLen, int nonce, const c

size_t JsonWriteJoinReply(char* dest, size_t maxLen, const char* userId, int reply, int nonce);

size_t JsonWriteOpenOverlayActivityInvite(char* dest,
size_t maxLen,
int8_t type,
int nonce,
int pid);

size_t JsonWriteOpenOverlayGuildInvite(char* dest,
size_t maxLen,
const char* code,
int nonce,
int pid);

// I want to use as few allocations as I can get away with, and to do that with RapidJson, you need
// to supply some of your own allocators for stuff rather than use the defaults

Expand Down

0 comments on commit a68bb5c

Please sign in to comment.