diff --git a/examples/button-clicker/Assets/DiscordController.cs b/examples/button-clicker/Assets/DiscordController.cs index 3294767..182d31d 100644 --- a/examples/button-clicker/Assets/DiscordController.cs +++ b/examples/button-clicker/Assets/DiscordController.cs @@ -7,7 +7,7 @@ public class DiscordJoinEvent : UnityEngine.Events.UnityEvent { } public class DiscordSpectateEvent : UnityEngine.Events.UnityEvent { } [System.Serializable] -public class DiscordJoinRequestEvent : UnityEngine.Events.UnityEvent { } +public class DiscordJoinRequestEvent : UnityEngine.Events.UnityEvent { } public class DiscordController : MonoBehaviour { @@ -16,7 +16,7 @@ public class DiscordController : MonoBehaviour public string optionalSteamId; public int callbackCalls; public int clickCounter; - public DiscordRpc.JoinRequest joinRequest; + public DiscordRpc.DiscordUser joinRequest; public UnityEngine.Events.UnityEvent onConnect; public UnityEngine.Events.UnityEvent onDisconnect; public UnityEngine.Events.UnityEvent hasResponded; @@ -50,10 +50,10 @@ public class DiscordController : MonoBehaviour hasResponded.Invoke(); } - public void ReadyCallback() + public void ReadyCallback(ref DiscordRpc.DiscordUser connectedUser) { ++callbackCalls; - Debug.Log("Discord: ready"); + Debug.Log(string.Format("Discord: connected to {0}#{1}: {2}", connectedUser.username, connectedUser.discriminator, connectedUser.userId)); onConnect.Invoke(); } @@ -84,7 +84,7 @@ public class DiscordController : MonoBehaviour onSpectate.Invoke(secret); } - public void RequestCallback(ref DiscordRpc.JoinRequest request) + public void RequestCallback(ref DiscordRpc.DiscordUser request) { ++callbackCalls; Debug.Log(string.Format("Discord: join request {0}#{1}: {2}", request.username, request.discriminator, request.userId)); diff --git a/examples/button-clicker/Assets/DiscordRpc.cs b/examples/button-clicker/Assets/DiscordRpc.cs index b3f6ffd..dec1ade 100644 --- a/examples/button-clicker/Assets/DiscordRpc.cs +++ b/examples/button-clicker/Assets/DiscordRpc.cs @@ -6,7 +6,7 @@ using System.Text; public class DiscordRpc { [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void ReadyCallback(); + public delegate void ReadyCallback(ref DiscordUser connectedUser); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void DisconnectedCallback(int errorCode, string message); @@ -21,7 +21,7 @@ public class DiscordRpc public delegate void SpectateCallback(string secret); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void RequestCallback(ref JoinRequest request); + public delegate void RequestCallback(ref DiscordUser request); public struct EventHandlers { @@ -54,7 +54,7 @@ public class DiscordRpc } [Serializable] - public struct JoinRequest + public struct DiscordUser { public string userId; public string username; diff --git a/examples/send-presence/send-presence.c b/examples/send-presence/send-presence.c index e4356e9..5449cf8 100644 --- a/examples/send-presence/send-presence.c +++ b/examples/send-presence/send-presence.c @@ -52,14 +52,18 @@ static void updateDiscordPresence() discordPresence.spectateSecret = "look"; discordPresence.instance = 0; Discord_UpdatePresence(&discordPresence); - } else { + } + else { Discord_ClearPresence(); } } -static void handleDiscordReady(void) +static void handleDiscordReady(const DiscordUser* connectedUser) { - printf("\nDiscord: ready\n"); + printf("\nDiscord: connected to user %s#%s - %s\n", + connectedUser->username, + connectedUser->discriminator, + connectedUser->userId); } static void handleDiscordDisconnected(int errcode, const char* message) @@ -82,13 +86,13 @@ static void handleDiscordSpectate(const char* secret) printf("\nDiscord: spectate (%s)\n", secret); } -static void handleDiscordJoinRequest(const DiscordJoinRequest* request) +static void handleDiscordJoinRequest(const DiscordUser* request) { int response = -1; char yn[4]; - printf("\nDiscord: join request from %s - %s - %s\n", + printf("\nDiscord: join request from %s#%s - %s\n", request->username, - request->avatar, + request->discriminator, request->userId); do { printf("Accept? (y/n)"); @@ -152,7 +156,8 @@ static void gameLoop() if (SendPresence) { printf("Clearing presence information.\n"); SendPresence = 0; - } else { + } + else { printf("Restoring presence information.\n"); SendPresence = 1; } diff --git a/examples/unrealstatus/Content/ShowTheUILevel.umap b/examples/unrealstatus/Content/ShowTheUILevel.umap index 8da4651..bc0e5b7 100644 Binary files a/examples/unrealstatus/Content/ShowTheUILevel.umap and b/examples/unrealstatus/Content/ShowTheUILevel.umap differ diff --git a/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpcBlueprint.cpp b/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpcBlueprint.cpp index db0f096..95388df 100644 --- a/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpcBlueprint.cpp +++ b/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpcBlueprint.cpp @@ -6,12 +6,22 @@ DEFINE_LOG_CATEGORY(Discord) static UDiscordRpc* self = nullptr; -static void ReadyHandler() +static void ReadyHandler(const DiscordUser* connectedUser) { - UE_LOG(Discord, Log, TEXT("Discord connected")); + FDiscordUserData ud; + ud.userId = ANSI_TO_TCHAR(connectedUser->userId); + ud.username = ANSI_TO_TCHAR(connectedUser->username); + ud.discriminator = ANSI_TO_TCHAR(connectedUser->discriminator); + ud.avatar = ANSI_TO_TCHAR(connectedUser->avatar); + UE_LOG(Discord, + Log, + TEXT("Discord connected to %s - %s#%s"), + *ud.userId, + *ud.username, + *ud.discriminator); if (self) { self->IsConnected = true; - self->OnConnected.Broadcast(); + self->OnConnected.Broadcast(ud); } } @@ -52,22 +62,27 @@ static void SpectateGameHandler(const char* spectateSecret) } } -static void JoinRequestHandler(const DiscordJoinRequest* request) +static void JoinRequestHandler(const DiscordUser* request) { - FDiscordJoinRequestData jr; - jr.userId = ANSI_TO_TCHAR(request->userId); - jr.username = ANSI_TO_TCHAR(request->username); - jr.discriminator = ANSI_TO_TCHAR(request->discriminator); - jr.avatar = ANSI_TO_TCHAR(request->avatar); - UE_LOG(Discord, Log, TEXT("Discord join request from %s - %s#%s"), *jr.userId, *jr.username, *jr.discriminator); + FDiscordUserData ud; + ud.userId = ANSI_TO_TCHAR(request->userId); + ud.username = ANSI_TO_TCHAR(request->username); + ud.discriminator = ANSI_TO_TCHAR(request->discriminator); + ud.avatar = ANSI_TO_TCHAR(request->avatar); + UE_LOG(Discord, + Log, + TEXT("Discord join request from %s - %s#%s"), + *ud.userId, + *ud.username, + *ud.discriminator); if (self) { - self->OnJoinRequest.Broadcast(jr); + self->OnJoinRequest.Broadcast(ud); } } void UDiscordRpc::Initialize(const FString& applicationId, - bool autoRegister, - const FString& optionalSteamId) + bool autoRegister, + const FString& optionalSteamId) { self = this; IsConnected = false; @@ -87,7 +102,7 @@ void UDiscordRpc::Initialize(const FString& applicationId, auto appId = StringCast(*applicationId); auto steamId = StringCast(*optionalSteamId); Discord_Initialize( - (const char*)appId.Get(), &handlers, autoRegister, (const char*)steamId.Get()); + (const char*)appId.Get(), &handlers, autoRegister, (const char*)steamId.Get()); } void UDiscordRpc::Shutdown() diff --git a/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Public/DiscordRpcBlueprint.h b/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Public/DiscordRpcBlueprint.h index 9e71302..2d65211 100644 --- a/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Public/DiscordRpcBlueprint.h +++ b/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Public/DiscordRpcBlueprint.h @@ -11,7 +11,7 @@ * Ask to join callback data */ USTRUCT(BlueprintType) -struct FDiscordJoinRequestData { +struct FDiscordUserData { GENERATED_USTRUCT_BODY() UPROPERTY(BlueprintReadOnly) @@ -27,12 +27,12 @@ struct FDiscordJoinRequestData { DECLARE_LOG_CATEGORY_EXTERN(Discord, Log, All); -DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDiscordConnected); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordConnected, const FDiscordUserData&, joinRequest); DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FDiscordDisconnected, int, errorCode, const FString&, errorMessage); DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FDiscordErrored, int, errorCode, const FString&, errorMessage); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordJoin, const FString&, joinSecret); DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordSpectate, const FString&, spectateSecret); -DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordJoinRequest, const FDiscordJoinRequestData&, joinRequest); +DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordJoinRequest, const FDiscordUserData&, joinRequest); // clang-format on diff --git a/include/discord_rpc.h b/include/discord_rpc.h index 72e5a4f..3e1441e 100644 --- a/include/discord_rpc.h +++ b/include/discord_rpc.h @@ -41,20 +41,20 @@ typedef struct DiscordRichPresence { int8_t instance; } DiscordRichPresence; -typedef struct DiscordJoinRequest { +typedef struct DiscordUser { const char* userId; const char* username; const char* discriminator; const char* avatar; -} DiscordJoinRequest; +} DiscordUser; typedef struct DiscordEventHandlers { - void (*ready)(void); + void (*ready)(const DiscordUser* request); void (*disconnected)(int errorCode, const char* message); void (*errored)(int errorCode, const char* message); void (*joinGame)(const char* joinSecret); void (*spectateGame)(const char* spectateSecret); - void (*joinRequest)(const DiscordJoinRequest* request); + void (*joinRequest)(const DiscordUser* request); } DiscordEventHandlers; #define DISCORD_REPLY_NO 0 diff --git a/src/discord_rpc.cpp b/src/discord_rpc.cpp index 3dd3a74..63ad405 100644 --- a/src/discord_rpc.cpp +++ b/src/discord_rpc.cpp @@ -32,7 +32,7 @@ struct QueuedMessage { } }; -struct JoinRequest { +struct User { // snowflake (64bit int), turned into a ascii decimal string, at most 20 chars +1 null // terminator = 21 char userId[32]; @@ -64,7 +64,8 @@ static std::mutex PresenceMutex; static std::mutex HandlerMutex; static QueuedMessage QueuedPresence{}; static MsgQueue SendQueue; -static MsgQueue JoinAskQueue; +static MsgQueue JoinAskQueue; +static User connectedUser; // We want to auto connect, and retry on failure, but not as fast as possible. This does expoential // backoff from 0.5 seconds to 1 minute @@ -292,7 +293,6 @@ extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId, } Handlers = {}; - } if (Connection) { @@ -300,8 +300,27 @@ extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId, } Connection = RpcConnection::Create(applicationId); - Connection->onConnect = []() { + Connection->onConnect = [](JsonDocument& readyMessage) { Discord_UpdateHandlers(&QueuedHandlers); + auto data = GetObjMember(&readyMessage, "data"); + auto user = GetObjMember(data, "user"); + auto userId = GetStrMember(user, "id"); + auto username = GetStrMember(user, "username"); + auto avatar = GetStrMember(user, "avatar"); + if (userId && username) { + StringCopy(connectedUser.userId, userId); + StringCopy(connectedUser.username, username); + auto discriminator = GetStrMember(user, "discriminator"); + if (discriminator) { + StringCopy(connectedUser.discriminator, discriminator); + } + if (avatar) { + StringCopy(connectedUser.avatar, avatar); + } + else { + connectedUser.avatar[0] = 0; + } + } WasJustConnected.exchange(true); ReconnectTimeMs.reset(); }; @@ -336,7 +355,7 @@ extern "C" DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence* { std::lock_guard guard(PresenceMutex); QueuedPresence.length = JsonWriteRichPresenceObj( - QueuedPresence.buffer, sizeof(QueuedPresence.buffer), Nonce++, Pid, presence); + QueuedPresence.buffer, sizeof(QueuedPresence.buffer), Nonce++, Pid, presence); } SignalIOActivity(); } @@ -385,7 +404,11 @@ extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) if (WasJustConnected.exchange(false)) { std::lock_guard guard(HandlerMutex); if (Handlers.ready) { - Handlers.ready(); + DiscordUser du{connectedUser.userId, + connectedUser.username, + connectedUser.discriminator, + connectedUser.avatar}; + Handlers.ready(&du); } } @@ -420,8 +443,8 @@ extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) { std::lock_guard guard(HandlerMutex); if (Handlers.joinRequest) { - DiscordJoinRequest djr{req->userId, req->username, req->discriminator, req->avatar}; - Handlers.joinRequest(&djr); + DiscordUser du{req->userId, req->username, req->discriminator, req->avatar}; + Handlers.joinRequest(&du); } } JoinAskQueue.CommitSend(); @@ -439,14 +462,13 @@ extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void) extern "C" DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* newHandlers) { if (newHandlers) { - -#define HANDLE_EVENT_REGISTRATION(handler_name, event) \ - if (!Handlers.handler_name && newHandlers->handler_name) { \ - RegisterForEvent(event); \ - } \ - else if (Handlers.handler_name && !newHandlers->handler_name) { \ - DeregisterForEvent(event); \ - } +#define HANDLE_EVENT_REGISTRATION(handler_name, event) \ + if (!Handlers.handler_name && newHandlers->handler_name) { \ + RegisterForEvent(event); \ + } \ + else if (Handlers.handler_name && !newHandlers->handler_name) { \ + DeregisterForEvent(event); \ + } std::lock_guard guard(HandlerMutex); HANDLE_EVENT_REGISTRATION(joinGame, "ACTIVITY_JOIN") @@ -457,8 +479,7 @@ extern "C" DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* newH Handlers = *newHandlers; } - else - { + else { std::lock_guard guard(HandlerMutex); Handlers = {}; } diff --git a/src/rpc_connection.cpp b/src/rpc_connection.cpp index b492de9..bf9e4cc 100644 --- a/src/rpc_connection.cpp +++ b/src/rpc_connection.cpp @@ -42,7 +42,7 @@ void RpcConnection::Open() if (cmd && evt && !strcmp(cmd, "DISPATCH") && !strcmp(evt, "READY")) { state = State::Connected; if (onConnect) { - onConnect(); + onConnect(message); } } } diff --git a/src/rpc_connection.h b/src/rpc_connection.h index d3c30d6..bbdd05c 100644 --- a/src/rpc_connection.h +++ b/src/rpc_connection.h @@ -40,7 +40,7 @@ struct RpcConnection { BaseConnection* connection{nullptr}; State state{State::Disconnected}; - void (*onConnect)(){nullptr}; + void (*onConnect)(JsonDocument& message){nullptr}; void (*onDisconnect)(int errorCode, const char* message){nullptr}; char appId[64]{}; int lastErrorCode{0};