Feedback via Discord in UE4

You can just download the class here if you’re lazy. mbpfl.h and mbpfl.cpp
- Create a BlueprintFunctionLibrary class in C++ and add these includes and defines.
#if PLATFORM_WINDOWS
#include "Windows/WindowsPlatformMisc.h"
#elif PLATFORM_LINUX
#include "Linux/LinuxPlatformMisc.h"
#elif PLATFORM_MAC
#include "Mac/MacPlatformMisc.h"
#endif
#include "GameFramework/GameUserSettings.h"
#define BUG_REPORT_WEBHOOK_URL "YOURWEBHOOKURLHERE"
#define MYGAME_VERSION "v1.0-pre-alpha"
#define DEFAULT_ICON_URL "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png"
- Add the following enums and structs to the header.
UENUM(BlueprintType)
enum class EBugReportCategory : uint8
{
Map,
Weapon,
Other
};
UENUM(BlueprintType)
enum class EBugReportPriority : uint8
{
Crash,
High,
Med,
Low
};
USTRUCT()
struct FDiscordMessageField
{
GENERATED_BODY()
UPROPERTY()
FString name;
UPROPERTY()
FString value;
UPROPERTY()
bool binline;
};
USTRUCT()
struct FDiscordMessageEmbedAuthor
{
GENERATED_BODY()
UPROPERTY()
FString name;
UPROPERTY()
FString url;
UPROPERTY()
FString icon_url;
FDiscordMessageEmbedAuthor() : url("https://trdwll.com"), icon_url(DEFAULT_ICON_URL) {}
};
USTRUCT()
struct FDiscordMessageEmbedFooter
{
GENERATED_BODY()
UPROPERTY()
FString text;
UPROPERTY()
FString icon_url;
FDiscordMessageEmbedFooter() : icon_url(DEFAULT_ICON_URL) {}
};
USTRUCT()
struct FDiscordMessageEmbed
{
GENERATED_BODY()
UPROPERTY()
FString title;
UPROPERTY()
FString description;
UPROPERTY()
uint32 color;
UPROPERTY()
TArray<FDiscordMessageField> fields;
UPROPERTY()
FDiscordMessageEmbedAuthor author;
UPROPERTY()
FDiscordMessageEmbedFooter footer;
UPROPERTY()
FString timestamp;
FDiscordMessageEmbed() : color(720640), timestamp(FDateTime::Now().ToIso8601()) {}
uint32 GetColor(const EBugReportPriority Priority)
{
switch (Priority)
{
case EBugReportPriority::Crash: return 16711680;
case EBugReportPriority::High: return 12389388;
case EBugReportPriority::Med: return 16742912;
default:
case EBugReportPriority::Low: return 720640;
}
}
};
USTRUCT()
struct FDiscordMessage
{
GENERATED_BODY()
UPROPERTY()
FString username;
UPROPERTY()
FString avatar_url;
UPROPERTY()
FString content;
UPROPERTY()
TArray<FDiscordMessageEmbed> embeds;
FDiscordMessage() : avatar_url(DEFAULT_ICON_URL) {}
};
USTRUCT(BlueprintType)
struct FBugReportUserData
{
GENERATED_BODY()
UPROPERTY(BlueprintReadWrite)
FString Author;
UPROPERTY(BlueprintReadWrite)
FVector Location;
UPROPERTY(BlueprintReadWrite)
FString MapName;
UPROPERTY(BlueprintReadWrite)
FString Message;
};- Add the following to your header file.
// Thanks to Rama for this method
// GetEnumValueAsString<EEnumType>("EEnumType", Value);
template<typename TEnum>
static FString GetEnumValueAsString(const FString& Name, TEnum Value)
{
const UEnum* enumPtr = FindObject<UEnum>(ANY_PACKAGE, *Name, true);
if (!enumPtr)
{
return FString("Invalid");
}
return enumPtr->GetNameByValue((int64)Value).ToString();
}
UFUNCTION(BlueprintCallable, Category = "Discord")
static void SubmitBugReport(const EBugReportCategory Category, const EBugReportPriority Priority, const FBugReportUserData& AuthorData, FString& ReportID, bool bIncludeSpecs = true);
/**
* Gets the number of RAM on the system
*/
UFUNCTION(BlueprintPure)
static FORCEINLINE int32 GetTotalRAM()
{
const FPlatformMemoryConstants& MemoryConstants = FPlatformMemory::GetConstants();
return MemoryConstants.TotalPhysicalGB;
}
UFUNCTION(BlueprintPure)
static FString GetGameResolution() { return *FString::Printf(TEXT("%dx%d"), UGameUserSettings::GetGameUserSettings()->GetScreenResolution().X, UGameUserSettings::GetGameUserSettings()->GetScreenResolution().Y); }
/**
* Gets the CPU Brand Name information.
*/
UFUNCTION(BlueprintPure)
static FString GetCPUBrandName()
{
#if PLATFORM_WINDOWS
return FWindowsPlatformMisc::GetCPUBrand();
#elif PLATFORM_LINUX
return FLinuxPlatformMisc::GetCPUBrand();
#elif PLATFORM_MAC
return FMacPlatformMisc::GetCPUBrand();
#endif
}
/**
* Gets the CPU Vendor Name information.
*/
UFUNCTION(BlueprintPure)
static FString GetCPUVendorName()
{
#if PLATFORM_WINDOWS
return FWindowsPlatformMisc::GetCPUVendor();
#elif PLATFORM_LINUX
return FLinuxPlatformMisc::GetCPUVendor();
#elif PLATFORM_MAC
return FMacPlatformMisc::GetCPUVendor();
#endif
}
/**
* Gets the GPU Brand Name information.
*/
UFUNCTION(BlueprintPure)
static FString GetGPUBrandName()
{
#if PLATFORM_WINDOWS
return FWindowsPlatformMisc::GetPrimaryGPUBrand();
#elif PLATFORM_LINUX
return FLinuxPlatformMisc::GetPrimaryGPUBrand();
#elif PLATFORM_MAC
return FMacPlatformMisc::GetPrimaryGPUBrand();
#endif
}
/**
* Gets the GPU Driver information.
*/
UFUNCTION(BlueprintPure)
static FORCEINLINE FString GetGPUDriverInfo() { return GRHIAdapterUserDriverVersion; }
In your BPFL source file add includes.
#include "Http.h"
#include "Interfaces/IHttpRequest.h"
#include "JsonObjectConverter.h"- The implementation for
SubmitBugReport.
void UMBPFL::SubmitBugReport(const EBugReportCategory Category, const EBugReportPriority Priority, const FBugReportUserData& AuthorData, FString& ReportID, bool bIncludeSpecs)
{
// Just some quick checks to prevent spamming
if (AuthorData.Author == "" || AuthorData.MapName == "" || AuthorData.Message == "")
{
return;
}
if (FHttpModule* http = &FHttpModule::Get())
{
TSharedRef<IHttpRequest> request = http->CreateRequest();
request->SetVerb("POST");
request->SetHeader("Content-Type", "application/json");
request->SetURL(BUG_REPORT_WEBHOOK_URL);
ReportID = FGuid::NewGuid().ToString();
// Create the embed for the report
FDiscordMessageEmbed embed;
embed.title = GetEnumValueAsString<EBugReportCategory>("EBugReportCategory", Category);
embed.author.icon_url = "";
embed.author.name = AuthorData.Author;
embed.description = AuthorData.Message;
embed.color = embed.GetColor(Priority);
embed.fields.Add({ "Priority", GetEnumValueAsString<EBugReportPriority>("EBugReportPriority", Priority) });
embed.fields.Add({ "Location", AuthorData.Location.ToString(), true });
embed.fields.Add({ "Map", AuthorData.MapName, true });
embed.footer.text = FString::Printf(TEXT("MYGame %s | %s"), *FString(MYGAME_VERSION), *ReportID);
FDiscordMessage data;
data.username = "Bug Reporter";
data.embeds.Add(embed);
// Don't show "private" information unless the player wants to
if (bIncludeSpecs)
{
// Create another embed for the users pc specs
FDiscordMessageEmbed embed2;
embed2.title = FString::Printf(TEXT("%s PC Specs"), *AuthorData.Author);
embed2.color = embed.GetColor(Priority);
embed2.fields.Add({ "Resolution", GetGameResolution(), true });
embed2.fields.Add({ "RAM", FString::Printf(TEXT("%dGB"), GetTotalRAM()), true });
embed2.fields.Add({ "CPU", GetCPUBrandName(), true });
embed2.fields.Add({ "GPU", GetGPUBrandName(), true });
embed2.fields.Add({ "GPU Driver", GetGPUDriverInfo(), true });
data.embeds.Add(embed2);
}
FString OutputString;
FJsonObjectConverter::UStructToJsonObjectString(data, OutputString);
OutputString = OutputString.Replace(TEXT("binline"), TEXT("inline"));
request->SetContentAsString(OutputString);
request->ProcessRequest();
}
}- Add
"Http", "Json", "JsonUtilities", "RHI"to your Project.Build.cs under PublicDependencyModuleNames. - Head on over to your discord server Server Settings -> Integrations -> Create Webhook. Then replace the URL for BUG_REPORT_WEBHOOK_URL with the one it gives you. until next time