Added more UE4 blueprint support
Added blueprint support for JoinRequest() and Respond, added latent blueprint node for getting Discord profile images
This commit is contained in:
@@ -1,7 +1,7 @@
|
||||
|
||||
|
||||
#include "DiscordRpcBlueprint.h"
|
||||
|
||||
#include "Blueprint/AsyncTaskDownloadImage.h"
|
||||
#include "discord-rpc.h"
|
||||
|
||||
DEFINE_LOG_CATEGORY(Discord)
|
||||
@@ -53,6 +53,29 @@ static void SpectateGameHandler(const char* spectateSecret)
|
||||
}
|
||||
}
|
||||
|
||||
static void JoinRequestReceiveHandler(const DiscordJoinRequest* joinRequestPayload)
|
||||
{
|
||||
if (!joinRequestPayload)
|
||||
{
|
||||
UE_LOG(Discord, Log, TEXT("received invalid Discord join request payload"));
|
||||
return;
|
||||
}
|
||||
|
||||
// wrap the payload with USTRUCT
|
||||
FDiscordJoinRequestPayload payloadContainer(joinRequestPayload);
|
||||
|
||||
UE_LOG(Discord, Log, TEXT("Discord join request from username: %s, UserID: %s, Avatar: %s"), *payloadContainer.Username,
|
||||
*payloadContainer.UserID,
|
||||
*payloadContainer.Avatar);
|
||||
|
||||
if (self) {
|
||||
// add to pending requests map
|
||||
self->PendingJoinRequests.Add(payloadContainer.UserID, payloadContainer);
|
||||
|
||||
self->OnJoinRequest.Broadcast(payloadContainer);
|
||||
}
|
||||
}
|
||||
|
||||
void UDiscordRpc::Initialize(const FString& applicationId,
|
||||
bool autoRegister,
|
||||
const FString& optionalSteamId)
|
||||
@@ -63,6 +86,10 @@ void UDiscordRpc::Initialize(const FString& applicationId,
|
||||
handlers.ready = ReadyHandler;
|
||||
handlers.disconnected = DisconnectHandler;
|
||||
handlers.errored = ErroredHandler;
|
||||
if (OnJoinRequest.IsBound())
|
||||
{
|
||||
handlers.joinRequest = JoinRequestReceiveHandler;
|
||||
}
|
||||
if (OnJoin.IsBound()) {
|
||||
handlers.joinGame = JoinGameHandler;
|
||||
}
|
||||
@@ -128,3 +155,65 @@ void UDiscordRpc::UpdatePresence()
|
||||
|
||||
Discord_UpdatePresence(&rp);
|
||||
}
|
||||
|
||||
void UDiscordRpc::RespondToDiscordJoinRequest(FString DiscordUserID, EDiscordJoinRequestResponse response)
|
||||
{
|
||||
// send the response to discord
|
||||
Discord_Respond(TCHAR_TO_ANSI(*DiscordUserID), static_cast<int>(response));
|
||||
|
||||
// remove userID entry from current join requests map
|
||||
PendingJoinRequests.FindAndRemoveChecked(DiscordUserID);
|
||||
}
|
||||
|
||||
UAsyncDiscordFetchAvatar::UAsyncDiscordFetchAvatar(const FObjectInitializer& ObjectInitializer)
|
||||
: Super(ObjectInitializer)
|
||||
{
|
||||
if (HasAnyFlags(RF_ClassDefaultObject) == false)
|
||||
{
|
||||
AddToRoot();
|
||||
}
|
||||
}
|
||||
|
||||
UAsyncDiscordFetchAvatar* UAsyncDiscordFetchAvatar::DiscordFetchAvatar(FString UserID, FString Avatar)
|
||||
{
|
||||
FString userProfileUrl = FString("http://cdn.discordapp.com/avatars/") + UserID + FString("/") + Avatar + FString(".jpg?size=512");
|
||||
|
||||
UE_LOG(Discord, Log, TEXT("Pulling Discord profile avatar image from %s"), *userProfileUrl);
|
||||
|
||||
// create the download image async task
|
||||
UAsyncTaskDownloadImage* asyncImageDl = UAsyncTaskDownloadImage::DownloadImage(userProfileUrl);
|
||||
|
||||
UAsyncDiscordFetchAvatar* fetchAsyncTask = NewObject<UAsyncDiscordFetchAvatar>();
|
||||
|
||||
if (fetchAsyncTask)
|
||||
{
|
||||
fetchAsyncTask->BindDelegates(asyncImageDl);
|
||||
fetchAsyncTask->ImageTask = asyncImageDl;
|
||||
}
|
||||
|
||||
return fetchAsyncTask;
|
||||
}
|
||||
|
||||
void UAsyncDiscordFetchAvatar::BindDelegates(UAsyncTaskDownloadImage* imageTask)
|
||||
{
|
||||
if (imageTask)
|
||||
{
|
||||
imageTask->OnSuccess.AddDynamic(this, &UAsyncDiscordFetchAvatar::OnImageDownloadSuccess);
|
||||
imageTask->OnFail.AddDynamic(this, &UAsyncDiscordFetchAvatar::OnImageDownloadFailed);
|
||||
}
|
||||
}
|
||||
|
||||
void UAsyncDiscordFetchAvatar::OnImageDownloadSuccess(UTexture2DDynamic* texture)
|
||||
{
|
||||
Successful.Broadcast(texture, UserID);
|
||||
|
||||
RemoveFromRoot();
|
||||
}
|
||||
|
||||
void UAsyncDiscordFetchAvatar::OnImageDownloadFailed(UTexture2DDynamic* texture)
|
||||
{
|
||||
Failed.Broadcast(texture, UserID);
|
||||
|
||||
RemoveFromRoot();
|
||||
}
|
||||
|
||||
|
@@ -3,19 +3,57 @@
|
||||
#pragma once
|
||||
|
||||
#include "CoreMinimal.h"
|
||||
#include "Kismet/BlueprintAsyncActionBase.h"
|
||||
#include "discord-rpc.h"
|
||||
#include "DiscordRpcBlueprint.generated.h"
|
||||
#include "Engine.h"
|
||||
|
||||
// unreal's header tool hates clang-format
|
||||
// clang-format off
|
||||
|
||||
DECLARE_LOG_CATEGORY_EXTERN(Discord, Log, All);
|
||||
|
||||
USTRUCT(BlueprintType)
|
||||
struct FDiscordJoinRequestPayload
|
||||
{
|
||||
GENERATED_BODY()
|
||||
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
FString UserID;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
FString Username;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
FString Avatar;
|
||||
|
||||
FDiscordJoinRequestPayload()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
FDiscordJoinRequestPayload(const DiscordJoinRequest* request)
|
||||
{
|
||||
if (request)
|
||||
{
|
||||
UserID = FString(ANSI_TO_TCHAR(request->userId));
|
||||
Username = FString(ANSI_TO_TCHAR(request->username));
|
||||
Avatar = FString(ANSI_TO_TCHAR(request->avatar));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
UENUM(BlueprintType)
|
||||
enum class EDiscordJoinRequestResponse : uint8
|
||||
{
|
||||
DJR_NO = DISCORD_REPLY_NO UMETA(DisplayName = "Yes"),
|
||||
DJR_YES = DISCORD_REPLY_YES UMETA(DisplayName = "No"),
|
||||
DJR_IGNORE = DISCORD_REPLY_IGNORE UMETA(DisplayName = "Ignore")
|
||||
};
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDiscordConnected);
|
||||
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, FDiscordJoinRequestPayload, request);
|
||||
|
||||
// clang-format on
|
||||
|
||||
@@ -114,6 +152,12 @@ public:
|
||||
Category = "Discord")
|
||||
FDiscordJoin OnJoin;
|
||||
|
||||
// when a user presses ask to join, this will trigger on the user that is getting the request
|
||||
UPROPERTY(BlueprintAssignable,
|
||||
meta = (DisplayName = "When Discord user presses Ask to join, this will be called on the client requested", Keywords = "Discord rpc"),
|
||||
Category = "Discord")
|
||||
FDiscordJoinRequest OnJoinRequest;
|
||||
|
||||
UPROPERTY(BlueprintAssignable,
|
||||
meta = (DisplayName = "When Discord user presses spectate", Keywords = "Discord rpc"),
|
||||
Category = "Discord")
|
||||
@@ -123,4 +167,46 @@ public:
|
||||
meta = (DisplayName = "Rich presence info", Keywords = "Discord rpc"),
|
||||
Category = "Discord")
|
||||
FDiscordRichPresence RichPresence;
|
||||
|
||||
/** This map stores all of the current pending join requests*/
|
||||
UPROPERTY(BlueprintReadOnly, meta = (Keywords = "Discord rpc"), Category = "Discord")
|
||||
TMap<FString, FDiscordJoinRequestPayload> PendingJoinRequests;
|
||||
|
||||
UFUNCTION(BlueprintCallable, meta = (Keywords = "Discord rpc"), Category = "Discord")
|
||||
void RespondToDiscordJoinRequest(FString DiscordUserID, EDiscordJoinRequestResponse response);
|
||||
};
|
||||
|
||||
class UTexture2DDynamic;
|
||||
|
||||
DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FDiscordFetchAvatarCompleted, UTexture2DDynamic*, Texture, FString, UserID);
|
||||
|
||||
UCLASS()
|
||||
class DISCORDRPC_API UAsyncDiscordFetchAvatar : public UBlueprintAsyncActionBase
|
||||
{
|
||||
GENERATED_UCLASS_BODY()
|
||||
|
||||
public:
|
||||
UFUNCTION(BlueprintCallable, meta = (BlueprintInternalUseOnly = "true", Keywords = "Discord rpc"), Category = "Discord")
|
||||
static UAsyncDiscordFetchAvatar* DiscordFetchAvatar(FString UserID, FString Avatar);
|
||||
|
||||
UFUNCTION()
|
||||
void BindDelegates(UAsyncTaskDownloadImage* imageTask);
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FDiscordFetchAvatarCompleted Successful;
|
||||
|
||||
UPROPERTY(BlueprintAssignable)
|
||||
FDiscordFetchAvatarCompleted Failed;
|
||||
|
||||
UPROPERTY()
|
||||
UAsyncTaskDownloadImage* ImageTask;
|
||||
|
||||
UPROPERTY()
|
||||
FString UserID;
|
||||
|
||||
UFUNCTION()
|
||||
void OnImageDownloadSuccess(UTexture2DDynamic* texture);
|
||||
|
||||
UFUNCTION()
|
||||
void OnImageDownloadFailed(UTexture2DDynamic* texture);
|
||||
};
|
||||
|
@@ -41,7 +41,8 @@ public class discordrpc : ModuleRules
|
||||
"SlateCore",
|
||||
"Core",
|
||||
"discordrpcLibrary",
|
||||
"Projects"
|
||||
"Projects",
|
||||
"UMG"
|
||||
// ... add other public dependencies that you statically link with here ...
|
||||
}
|
||||
);
|
||||
|
Reference in New Issue
Block a user