Adding user object to READY event (#159)

* Pass the READY event data down in onConnect

* Changes made for UE4 and Unity wrappers

* Changing object name from joinRequest to DiscordUser
This commit is contained in:
Mason Sciotti 2018-04-16 10:25:44 -07:00 committed by GitHub
parent 2ce9fe068b
commit 64027b336f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 97 additions and 56 deletions

View file

@ -7,7 +7,7 @@ public class DiscordJoinEvent : UnityEngine.Events.UnityEvent<string> { }
public class DiscordSpectateEvent : UnityEngine.Events.UnityEvent<string> { } public class DiscordSpectateEvent : UnityEngine.Events.UnityEvent<string> { }
[System.Serializable] [System.Serializable]
public class DiscordJoinRequestEvent : UnityEngine.Events.UnityEvent<DiscordRpc.JoinRequest> { } public class DiscordJoinRequestEvent : UnityEngine.Events.UnityEvent<DiscordRpc.DiscordUser> { }
public class DiscordController : MonoBehaviour public class DiscordController : MonoBehaviour
{ {
@ -16,7 +16,7 @@ public class DiscordController : MonoBehaviour
public string optionalSteamId; public string optionalSteamId;
public int callbackCalls; public int callbackCalls;
public int clickCounter; public int clickCounter;
public DiscordRpc.JoinRequest joinRequest; public DiscordRpc.DiscordUser joinRequest;
public UnityEngine.Events.UnityEvent onConnect; public UnityEngine.Events.UnityEvent onConnect;
public UnityEngine.Events.UnityEvent onDisconnect; public UnityEngine.Events.UnityEvent onDisconnect;
public UnityEngine.Events.UnityEvent hasResponded; public UnityEngine.Events.UnityEvent hasResponded;
@ -50,10 +50,10 @@ public class DiscordController : MonoBehaviour
hasResponded.Invoke(); hasResponded.Invoke();
} }
public void ReadyCallback() public void ReadyCallback(ref DiscordRpc.DiscordUser connectedUser)
{ {
++callbackCalls; ++callbackCalls;
Debug.Log("Discord: ready"); Debug.Log(string.Format("Discord: connected to {0}#{1}: {2}", connectedUser.username, connectedUser.discriminator, connectedUser.userId));
onConnect.Invoke(); onConnect.Invoke();
} }
@ -84,7 +84,7 @@ public class DiscordController : MonoBehaviour
onSpectate.Invoke(secret); onSpectate.Invoke(secret);
} }
public void RequestCallback(ref DiscordRpc.JoinRequest request) public void RequestCallback(ref DiscordRpc.DiscordUser request)
{ {
++callbackCalls; ++callbackCalls;
Debug.Log(string.Format("Discord: join request {0}#{1}: {2}", request.username, request.discriminator, request.userId)); Debug.Log(string.Format("Discord: join request {0}#{1}: {2}", request.username, request.discriminator, request.userId));

View file

@ -6,7 +6,7 @@ using System.Text;
public class DiscordRpc public class DiscordRpc
{ {
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void ReadyCallback(); public delegate void ReadyCallback(ref DiscordUser connectedUser);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void DisconnectedCallback(int errorCode, string message); public delegate void DisconnectedCallback(int errorCode, string message);
@ -21,7 +21,7 @@ public class DiscordRpc
public delegate void SpectateCallback(string secret); public delegate void SpectateCallback(string secret);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)] [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate void RequestCallback(ref JoinRequest request); public delegate void RequestCallback(ref DiscordUser request);
public struct EventHandlers public struct EventHandlers
{ {
@ -54,7 +54,7 @@ public class DiscordRpc
} }
[Serializable] [Serializable]
public struct JoinRequest public struct DiscordUser
{ {
public string userId; public string userId;
public string username; public string username;

View file

@ -52,14 +52,18 @@ static void updateDiscordPresence()
discordPresence.spectateSecret = "look"; discordPresence.spectateSecret = "look";
discordPresence.instance = 0; discordPresence.instance = 0;
Discord_UpdatePresence(&discordPresence); Discord_UpdatePresence(&discordPresence);
} else { }
else {
Discord_ClearPresence(); 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) static void handleDiscordDisconnected(int errcode, const char* message)
@ -82,13 +86,13 @@ static void handleDiscordSpectate(const char* secret)
printf("\nDiscord: spectate (%s)\n", secret); printf("\nDiscord: spectate (%s)\n", secret);
} }
static void handleDiscordJoinRequest(const DiscordJoinRequest* request) static void handleDiscordJoinRequest(const DiscordUser* request)
{ {
int response = -1; int response = -1;
char yn[4]; char yn[4];
printf("\nDiscord: join request from %s - %s - %s\n", printf("\nDiscord: join request from %s#%s - %s\n",
request->username, request->username,
request->avatar, request->discriminator,
request->userId); request->userId);
do { do {
printf("Accept? (y/n)"); printf("Accept? (y/n)");
@ -152,7 +156,8 @@ static void gameLoop()
if (SendPresence) { if (SendPresence) {
printf("Clearing presence information.\n"); printf("Clearing presence information.\n");
SendPresence = 0; SendPresence = 0;
} else { }
else {
printf("Restoring presence information.\n"); printf("Restoring presence information.\n");
SendPresence = 1; SendPresence = 1;
} }

View file

@ -6,12 +6,22 @@ DEFINE_LOG_CATEGORY(Discord)
static UDiscordRpc* self = nullptr; 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) { if (self) {
self->IsConnected = true; 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; FDiscordUserData ud;
jr.userId = ANSI_TO_TCHAR(request->userId); ud.userId = ANSI_TO_TCHAR(request->userId);
jr.username = ANSI_TO_TCHAR(request->username); ud.username = ANSI_TO_TCHAR(request->username);
jr.discriminator = ANSI_TO_TCHAR(request->discriminator); ud.discriminator = ANSI_TO_TCHAR(request->discriminator);
jr.avatar = ANSI_TO_TCHAR(request->avatar); ud.avatar = ANSI_TO_TCHAR(request->avatar);
UE_LOG(Discord, Log, TEXT("Discord join request from %s - %s#%s"), *jr.userId, *jr.username, *jr.discriminator); UE_LOG(Discord,
Log,
TEXT("Discord join request from %s - %s#%s"),
*ud.userId,
*ud.username,
*ud.discriminator);
if (self) { if (self) {
self->OnJoinRequest.Broadcast(jr); self->OnJoinRequest.Broadcast(ud);
} }
} }
void UDiscordRpc::Initialize(const FString& applicationId, void UDiscordRpc::Initialize(const FString& applicationId,
bool autoRegister, bool autoRegister,
const FString& optionalSteamId) const FString& optionalSteamId)
{ {
self = this; self = this;
IsConnected = false; IsConnected = false;
@ -87,7 +102,7 @@ void UDiscordRpc::Initialize(const FString& applicationId,
auto appId = StringCast<ANSICHAR>(*applicationId); auto appId = StringCast<ANSICHAR>(*applicationId);
auto steamId = StringCast<ANSICHAR>(*optionalSteamId); auto steamId = StringCast<ANSICHAR>(*optionalSteamId);
Discord_Initialize( 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() void UDiscordRpc::Shutdown()

View file

@ -11,7 +11,7 @@
* Ask to join callback data * Ask to join callback data
*/ */
USTRUCT(BlueprintType) USTRUCT(BlueprintType)
struct FDiscordJoinRequestData { struct FDiscordUserData {
GENERATED_USTRUCT_BODY() GENERATED_USTRUCT_BODY()
UPROPERTY(BlueprintReadOnly) UPROPERTY(BlueprintReadOnly)
@ -27,12 +27,12 @@ struct FDiscordJoinRequestData {
DECLARE_LOG_CATEGORY_EXTERN(Discord, Log, All); 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(FDiscordDisconnected, int, errorCode, const FString&, errorMessage);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FDiscordErrored, 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(FDiscordJoin, const FString&, joinSecret);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordSpectate, const FString&, spectateSecret); 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 // clang-format on

View file

@ -41,20 +41,20 @@ typedef struct DiscordRichPresence {
int8_t instance; int8_t instance;
} DiscordRichPresence; } DiscordRichPresence;
typedef struct DiscordJoinRequest { typedef struct DiscordUser {
const char* userId; const char* userId;
const char* username; const char* username;
const char* discriminator; const char* discriminator;
const char* avatar; const char* avatar;
} DiscordJoinRequest; } DiscordUser;
typedef struct DiscordEventHandlers { typedef struct DiscordEventHandlers {
void (*ready)(void); void (*ready)(const DiscordUser* request);
void (*disconnected)(int errorCode, const char* message); void (*disconnected)(int errorCode, const char* message);
void (*errored)(int errorCode, const char* message); void (*errored)(int errorCode, const char* message);
void (*joinGame)(const char* joinSecret); void (*joinGame)(const char* joinSecret);
void (*spectateGame)(const char* spectateSecret); void (*spectateGame)(const char* spectateSecret);
void (*joinRequest)(const DiscordJoinRequest* request); void (*joinRequest)(const DiscordUser* request);
} DiscordEventHandlers; } DiscordEventHandlers;
#define DISCORD_REPLY_NO 0 #define DISCORD_REPLY_NO 0

View file

@ -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 // snowflake (64bit int), turned into a ascii decimal string, at most 20 chars +1 null
// terminator = 21 // terminator = 21
char userId[32]; char userId[32];
@ -64,7 +64,8 @@ static std::mutex PresenceMutex;
static std::mutex HandlerMutex; static std::mutex HandlerMutex;
static QueuedMessage QueuedPresence{}; static QueuedMessage QueuedPresence{};
static MsgQueue<QueuedMessage, MessageQueueSize> SendQueue; static MsgQueue<QueuedMessage, MessageQueueSize> SendQueue;
static MsgQueue<JoinRequest, JoinQueueSize> JoinAskQueue; static MsgQueue<User, JoinQueueSize> JoinAskQueue;
static User connectedUser;
// We want to auto connect, and retry on failure, but not as fast as possible. This does expoential // 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 // backoff from 0.5 seconds to 1 minute
@ -292,7 +293,6 @@ extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
} }
Handlers = {}; Handlers = {};
} }
if (Connection) { if (Connection) {
@ -300,8 +300,27 @@ extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
} }
Connection = RpcConnection::Create(applicationId); Connection = RpcConnection::Create(applicationId);
Connection->onConnect = []() { Connection->onConnect = [](JsonDocument& readyMessage) {
Discord_UpdateHandlers(&QueuedHandlers); 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); WasJustConnected.exchange(true);
ReconnectTimeMs.reset(); ReconnectTimeMs.reset();
}; };
@ -336,7 +355,7 @@ extern "C" DISCORD_EXPORT void Discord_UpdatePresence(const DiscordRichPresence*
{ {
std::lock_guard<std::mutex> guard(PresenceMutex); std::lock_guard<std::mutex> guard(PresenceMutex);
QueuedPresence.length = JsonWriteRichPresenceObj( QueuedPresence.length = JsonWriteRichPresenceObj(
QueuedPresence.buffer, sizeof(QueuedPresence.buffer), Nonce++, Pid, presence); QueuedPresence.buffer, sizeof(QueuedPresence.buffer), Nonce++, Pid, presence);
} }
SignalIOActivity(); SignalIOActivity();
} }
@ -385,7 +404,11 @@ extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void)
if (WasJustConnected.exchange(false)) { if (WasJustConnected.exchange(false)) {
std::lock_guard<std::mutex> guard(HandlerMutex); std::lock_guard<std::mutex> guard(HandlerMutex);
if (Handlers.ready) { 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<std::mutex> guard(HandlerMutex); std::lock_guard<std::mutex> guard(HandlerMutex);
if (Handlers.joinRequest) { if (Handlers.joinRequest) {
DiscordJoinRequest djr{req->userId, req->username, req->discriminator, req->avatar}; DiscordUser du{req->userId, req->username, req->discriminator, req->avatar};
Handlers.joinRequest(&djr); Handlers.joinRequest(&du);
} }
} }
JoinAskQueue.CommitSend(); JoinAskQueue.CommitSend();
@ -439,14 +462,13 @@ extern "C" DISCORD_EXPORT void Discord_RunCallbacks(void)
extern "C" DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* newHandlers) extern "C" DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* newHandlers)
{ {
if (newHandlers) { if (newHandlers) {
#define HANDLE_EVENT_REGISTRATION(handler_name, event) \
#define HANDLE_EVENT_REGISTRATION(handler_name, event) \ if (!Handlers.handler_name && newHandlers->handler_name) { \
if (!Handlers.handler_name && newHandlers->handler_name) { \ RegisterForEvent(event); \
RegisterForEvent(event); \ } \
} \ else if (Handlers.handler_name && !newHandlers->handler_name) { \
else if (Handlers.handler_name && !newHandlers->handler_name) { \ DeregisterForEvent(event); \
DeregisterForEvent(event); \ }
}
std::lock_guard<std::mutex> guard(HandlerMutex); std::lock_guard<std::mutex> guard(HandlerMutex);
HANDLE_EVENT_REGISTRATION(joinGame, "ACTIVITY_JOIN") HANDLE_EVENT_REGISTRATION(joinGame, "ACTIVITY_JOIN")
@ -457,8 +479,7 @@ extern "C" DISCORD_EXPORT void Discord_UpdateHandlers(DiscordEventHandlers* newH
Handlers = *newHandlers; Handlers = *newHandlers;
} }
else else {
{
std::lock_guard<std::mutex> guard(HandlerMutex); std::lock_guard<std::mutex> guard(HandlerMutex);
Handlers = {}; Handlers = {};
} }

View file

@ -42,7 +42,7 @@ void RpcConnection::Open()
if (cmd && evt && !strcmp(cmd, "DISPATCH") && !strcmp(evt, "READY")) { if (cmd && evt && !strcmp(cmd, "DISPATCH") && !strcmp(evt, "READY")) {
state = State::Connected; state = State::Connected;
if (onConnect) { if (onConnect) {
onConnect(); onConnect(message);
} }
} }
} }

View file

@ -40,7 +40,7 @@ struct RpcConnection {
BaseConnection* connection{nullptr}; BaseConnection* connection{nullptr};
State state{State::Disconnected}; State state{State::Disconnected};
void (*onConnect)(){nullptr}; void (*onConnect)(JsonDocument& message){nullptr};
void (*onDisconnect)(int errorCode, const char* message){nullptr}; void (*onDisconnect)(int errorCode, const char* message){nullptr};
char appId[64]{}; char appId[64]{};
int lastErrorCode{0}; int lastErrorCode{0};