diff --git a/build.py b/build.py index 221ad6d..799db26 100755 --- a/build.py +++ b/build.py @@ -101,18 +101,18 @@ def unreal(ctx): click.echo('--- Copying libs and header into unreal example') - UNREAL_PROJECT_PATH = os.path.join(SCRIPT_PATH, 'examples', 'unrealstatus', 'plugins', 'discordrpc') + UNREAL_PROJECT_PATH = os.path.join(SCRIPT_PATH, 'examples', 'unrealstatus', 'Plugins', 'discordrpc') BUILD_BASE_PATH = os.path.join(SCRIPT_PATH, 'builds', 'win64-dynamic', 'src', 'Release') - UNREAL_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Binaries', 'ThirdParty', 'discordrpcLibrary', 'Win64') + UNREAL_DLL_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Win64') mkdir_p(UNREAL_DLL_PATH) shutil.copy(os.path.join(BUILD_BASE_PATH, 'discord-rpc.dll'), UNREAL_DLL_PATH) - UNREAL_INCLUDE_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'discordrpcLibrary', 'Include') + UNREAL_INCLUDE_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Include') mkdir_p(UNREAL_INCLUDE_PATH) shutil.copy(os.path.join(SCRIPT_PATH, 'include', 'discord-rpc.h'), UNREAL_INCLUDE_PATH) - UNREAL_LIB_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'discordrpcLibrary', 'x64', 'Release') + UNREAL_LIB_PATH = os.path.join(UNREAL_PROJECT_PATH, 'Source', 'ThirdParty', 'DiscordRpcLibrary', 'Win64') mkdir_p(UNREAL_LIB_PATH) shutil.copy(os.path.join(BUILD_BASE_PATH, 'discord-rpc.lib'), UNREAL_LIB_PATH) diff --git a/examples/unrealstatus/.gitignore b/examples/unrealstatus/.gitignore index ad5d402..bd472d5 100644 --- a/examples/unrealstatus/.gitignore +++ b/examples/unrealstatus/.gitignore @@ -73,3 +73,6 @@ Intermediate/ # Cache files for the editor to use DerivedDataCache/ + +# Library headers must be copied automatically by the build script (build.py unreal) +Plugins/DiscordRpc/Source/ThirdParty/DiscordRpcLibrary/Include diff --git a/examples/unrealstatus/Plugins/discordrpc/discordrpc.uplugin b/examples/unrealstatus/Plugins/discordrpc/DiscordRpc.uplugin similarity index 73% rename from examples/unrealstatus/Plugins/discordrpc/discordrpc.uplugin rename to examples/unrealstatus/Plugins/discordrpc/DiscordRpc.uplugin index ca77578..309df12 100644 --- a/examples/unrealstatus/Plugins/discordrpc/discordrpc.uplugin +++ b/examples/unrealstatus/Plugins/discordrpc/DiscordRpc.uplugin @@ -15,9 +15,15 @@ "Installed": false, "Modules": [ { - "Name": "discordrpc", - "Type": "Developer", - "LoadingPhase": "Default" + "Name": "DiscordRpc", + "Type": "Runtime", + "LoadingPhase": "PreDefault", + "WhitelistPlatforms" : + [ + "Win64", + "Linux", + "Mac" + ] } ] } \ No newline at end of file diff --git a/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/DiscordRpc.Build.cs b/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/DiscordRpc.Build.cs new file mode 100644 index 0000000..4b06325 --- /dev/null +++ b/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/DiscordRpc.Build.cs @@ -0,0 +1,57 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +using UnrealBuildTool; +using System.IO; + +public class DiscordRpc : ModuleRules +{ +#if WITH_FORWARDED_MODULE_RULES_CTOR + public DiscordRpc(ReadOnlyTargetRules Target) : base(Target) +#else + public DiscordRpc(TargetInfo Target) +#endif + { + Definitions.Add("DISCORD_DYNAMIC_LIB=1"); + + PublicIncludePaths.AddRange( + new string[] { + "DiscordRpc/Public" + } + ); + + PrivateIncludePaths.AddRange( + new string[] { + "DiscordRpc/Private" + } + ); + + PublicDependencyModuleNames.AddRange( + new string[] + { + "Core", + "DiscordRpcLibrary" + } + ); + + PrivateDependencyModuleNames.AddRange( + new string[] + { + "CoreUObject", + "Engine", + "Slate", + "SlateCore", + "Projects" + } + ); + + DynamicallyLoadedModuleNames.AddRange( + new string[] + { + // ... add any modules that your module loads dynamically here ... + } + ); + + string BaseDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "Source", "ThirdParty", "DiscordRpcLibrary")); + PublicIncludePaths.Add(Path.Combine(BaseDirectory, "Include")); + } +} \ No newline at end of file diff --git a/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpc.cpp b/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpc.cpp new file mode 100644 index 0000000..db70ad0 --- /dev/null +++ b/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpc.cpp @@ -0,0 +1,71 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#include "DiscordRpcPrivatePCH.h" +#include "IPluginManager.h" +#include "ModuleManager.h" + +#define LOCTEXT_NAMESPACE "FDiscordRpcModule" + +void FDiscordRpcModule::StartupModule() +{ +#if !PLATFORM_LINUX +#if defined(DISCORD_DYNAMIC_LIB) + // Get the base directory of this plugin + FString BaseDir = IPluginManager::Get().FindPlugin("DiscordRpc")->GetBaseDir(); + const FString SDKDir = FPaths::Combine(*BaseDir, TEXT("Source"), TEXT("ThirdParty"), TEXT("DiscordRpcLibrary")); +#if PLATFORM_WINDOWS + const FString LibName = TEXT("discord-rpc"); + const FString LibDir = FPaths::Combine(*SDKDir, TEXT("Win64")); + if (!LoadDependency(LibDir, LibName, DiscordRpcLibraryHandle)) { + FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT(LOCTEXT_NAMESPACE, "Failed to load DiscordRpc plugin. Plug-in will not be functional.")); + FreeDependency(DiscordRpcLibraryHandle); + } +#elif PLATFORM_MAC + const FString LibName = TEXT("libdiscord-rpc"); + const FString LibDir = FPaths::Combine(*SDKDir, TEXT("Mac")); + if (!LoadDependency(LibDir, LibName, DiscordRpcLibraryHandle)) { + FMessageDialog::Open(EAppMsgType::Ok, LOCTEXT(LOCTEXT_NAMESPACE, "Failed to load DiscordRpc plugin. Plug-in will not be functional.")); + FreeDependency(DiscordRpcLibraryHandle); + } +#endif +#endif +#endif +} + +void FDiscordRpcModule::ShutdownModule() +{ + // Free the dll handle +#if !PLATFORM_LINUX +#if defined(DISCORD_DYNAMIC_LIB) + FreeDependency(DiscordRpcLibraryHandle); +#endif +#endif +} + +bool FDiscordRpcModule::LoadDependency(const FString& Dir, const FString& Name, void*& Handle) +{ + FString Lib = Name + TEXT(".") + FPlatformProcess::GetModuleExtension(); + FString Path = Dir.IsEmpty() ? *Lib : FPaths::Combine(*Dir, *Lib); + + Handle = FPlatformProcess::GetDllHandle(*Path); + + if (Handle == nullptr) + { + return false; + } + + return true; +} + +void FDiscordRpcModule::FreeDependency(void*& Handle) +{ + if (Handle != nullptr) + { + FPlatformProcess::FreeDllHandle(Handle); + Handle = nullptr; + } +} + +#undef LOCTEXT_NAMESPACE + +IMPLEMENT_MODULE(FDiscordRpcModule, DiscordRpc) \ No newline at end of file diff --git a/examples/unrealstatus/Plugins/discordrpc/Source/discordrpc/Private/DiscordRpcBlueprint.cpp b/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpcBlueprint.cpp similarity index 95% rename from examples/unrealstatus/Plugins/discordrpc/Source/discordrpc/Private/DiscordRpcBlueprint.cpp rename to examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpcBlueprint.cpp index 5305806..fc6b21b 100644 --- a/examples/unrealstatus/Plugins/discordrpc/Source/discordrpc/Private/DiscordRpcBlueprint.cpp +++ b/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpcBlueprint.cpp @@ -1,7 +1,5 @@ - - +#include "DiscordRpcPrivatePCH.h" #include "DiscordRpcBlueprint.h" - #include "discord-rpc.h" DEFINE_LOG_CATEGORY(Discord) @@ -68,8 +66,8 @@ static void JoinRequestHandler(const DiscordJoinRequest* request) } void UDiscordRpc::Initialize(const FString& applicationId, - bool autoRegister, - const FString& optionalSteamId) + bool autoRegister, + const FString& optionalSteamId) { self = this; IsConnected = false; @@ -89,7 +87,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/Private/DiscordRpcPrivatePCH.h b/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpcPrivatePCH.h new file mode 100644 index 0000000..0c66aba --- /dev/null +++ b/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Private/DiscordRpcPrivatePCH.h @@ -0,0 +1,2 @@ +#include "Core.h" +#include "DiscordRpc.h" \ No newline at end of file diff --git a/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Public/DiscordRpc.h b/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Public/DiscordRpc.h new file mode 100644 index 0000000..727833b --- /dev/null +++ b/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Public/DiscordRpc.h @@ -0,0 +1,20 @@ +// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. + +#pragma once + +#include "ModuleManager.h" + +class FDiscordRpcModule : public IModuleInterface { +public: + /** IModuleInterface implementation */ + virtual void StartupModule() override; + virtual void ShutdownModule() override; + +private: + /** Handle to the test dll we will load */ + void* DiscordRpcLibraryHandle; + + /** StartupModule is covered with defines, these functions are the place to put breakpoints */ + static bool LoadDependency(const FString& Dir, const FString& Name, void*& Handle); + static void FreeDependency(void*& Handle); +}; \ No newline at end of file diff --git a/examples/unrealstatus/Plugins/discordrpc/Source/discordrpc/Public/DiscordRpcBlueprint.h b/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Public/DiscordRpcBlueprint.h similarity index 99% rename from examples/unrealstatus/Plugins/discordrpc/Source/discordrpc/Public/DiscordRpcBlueprint.h rename to examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Public/DiscordRpcBlueprint.h index e6c1e91..7fbad7b 100644 --- a/examples/unrealstatus/Plugins/discordrpc/Source/discordrpc/Public/DiscordRpcBlueprint.h +++ b/examples/unrealstatus/Plugins/discordrpc/Source/DiscordRpc/Public/DiscordRpcBlueprint.h @@ -1,5 +1,3 @@ - - #pragma once #include "CoreMinimal.h" diff --git a/examples/unrealstatus/Plugins/discordrpc/Source/ThirdParty/DiscordRpcLibrary/DiscordRpcLibrary.Build.cs b/examples/unrealstatus/Plugins/discordrpc/Source/ThirdParty/DiscordRpcLibrary/DiscordRpcLibrary.Build.cs new file mode 100644 index 0000000..ba8d834 --- /dev/null +++ b/examples/unrealstatus/Plugins/discordrpc/Source/ThirdParty/DiscordRpcLibrary/DiscordRpcLibrary.Build.cs @@ -0,0 +1,59 @@ +// Fill out your copyright notice in the Description page of Project Settings. + +using System.IO; +using UnrealBuildTool; + +public class DiscordRpcLibrary : ModuleRules +{ +#if WITH_FORWARDED_MODULE_RULES_CTOR + public DiscordRpcLibrary(ReadOnlyTargetRules Target) : base(Target) +#else + public DiscordRpcLibrary(TargetInfo Target) +#endif + { + Type = ModuleType.External; + Definitions.Add("DISCORD_DYNAMIC_LIB=1"); + + string BaseDirectory = Path.GetFullPath(Path.Combine(ModuleDirectory, "..", "..", "ThirdParty", "DiscordRpcLibrary")); + + if (Target.Platform == UnrealTargetPlatform.Win64) + { + string lib = Path.Combine(BaseDirectory, "Win64"); + + // Include headers + PublicIncludePaths.Add(Path.Combine(BaseDirectory, "Include")); + + // Add the import library + PublicLibraryPaths.Add(lib); + PublicAdditionalLibraries.Add(Path.Combine(lib, "discord-rpc.lib")); + + // Dynamic + RuntimeDependencies.Add(new RuntimeDependency(Path.Combine(lib, "discord-rpc.dll"))); + PublicDelayLoadDLLs.Add("discord-rpc.dll"); + } + else if (Target.Platform == UnrealTargetPlatform.Linux) + { + string lib = Path.Combine(BaseDirectory, "Linux", "x86_64-unknown-linux-gnu"); + + // Include headers + PublicIncludePaths.Add(Path.Combine(BaseDirectory, "Include")); + + // Add the import library + PublicLibraryPaths.Add(lib); + PublicAdditionalLibraries.Add(Path.Combine(lib, "libdiscord-rpc.so")); + RuntimeDependencies.Add(new RuntimeDependency(Path.Combine(lib, "libdiscord-rpc.so"))); + } + else if (Target.Platform == UnrealTargetPlatform.Mac) + { + string lib = Path.Combine(BaseDirectory, "Mac"); + + // Include headers + PublicIncludePaths.Add(Path.Combine(BaseDirectory, "Include")); + + // Add the import library + PublicLibraryPaths.Add(lib); + PublicAdditionalLibraries.Add(Path.Combine(lib, "libdiscord-rpc.dylib")); + RuntimeDependencies.Add(new RuntimeDependency(Path.Combine(lib, "libdiscord-rpc.dylib"))); + } + } +} \ No newline at end of file diff --git a/examples/unrealstatus/Plugins/discordrpc/Source/ThirdParty/discordrpcLibrary/discordrpcLibrary.Build.cs b/examples/unrealstatus/Plugins/discordrpc/Source/ThirdParty/discordrpcLibrary/discordrpcLibrary.Build.cs deleted file mode 100644 index ac67153..0000000 --- a/examples/unrealstatus/Plugins/discordrpc/Source/ThirdParty/discordrpcLibrary/discordrpcLibrary.Build.cs +++ /dev/null @@ -1,27 +0,0 @@ -// Fill out your copyright notice in the Description page of Project Settings. - -using System.IO; -using UnrealBuildTool; - -public class discordrpcLibrary : ModuleRules -{ - public discordrpcLibrary(ReadOnlyTargetRules Target) : base(Target) - { - Type = ModuleType.External; - - if (Target.Platform == UnrealTargetPlatform.Win64) - { - // Add the import library - PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "Include")); - PublicLibraryPaths.Add(Path.Combine(ModuleDirectory, "x64", "Release")); - PublicAdditionalLibraries.Add("discord-rpc.lib"); - - // Delay-load the DLL, so we can load it from the right place first - PublicDelayLoadDLLs.Add("discord-rpc.dll"); - } - else if (Target.Platform == UnrealTargetPlatform.Mac) - { - PublicDelayLoadDLLs.Add(Path.Combine(ModuleDirectory, "Mac", "Release", "libdiscord-rpc.dylib")); - } - } -} diff --git a/examples/unrealstatus/Plugins/discordrpc/Source/discordrpc/Private/discordrpc.cpp b/examples/unrealstatus/Plugins/discordrpc/Source/discordrpc/Private/discordrpc.cpp deleted file mode 100644 index dc5237a..0000000 --- a/examples/unrealstatus/Plugins/discordrpc/Source/discordrpc/Private/discordrpc.cpp +++ /dev/null @@ -1,50 +0,0 @@ -// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. - -#include "discordrpc.h" -#include "Core.h" -#include "IPluginManager.h" -#include "ModuleManager.h" - -#define LOCTEXT_NAMESPACE "FdiscordrpcModule" - -void FdiscordrpcModule::StartupModule() -{ - // This code will execute after your module is loaded into memory; the exact timing is specified - // in the .uplugin file per-module - - // Get the base directory of this plugin - FString BaseDir = IPluginManager::Get().FindPlugin("discordrpc")->GetBaseDir(); - - // Add on the relative location of the third party dll and load it - FString LibraryPath; -#if PLATFORM_WINDOWS - LibraryPath = FPaths::Combine( - *BaseDir, TEXT("Binaries/ThirdParty/discordrpcLibrary/Win64/discord-rpc.dll")); -#elif PLATFORM_MAC - LibraryPath = FPaths::Combine( - *BaseDir, TEXT("Source/ThirdParty/discordrpcLibrary/Mac/Release/libdiscord-rpc.dylib")); -#endif // PLATFORM_WINDOWS - - DiscordLibraryHandle = - !LibraryPath.IsEmpty() ? FPlatformProcess::GetDllHandle(*LibraryPath) : nullptr; - - if (!DiscordLibraryHandle) { - FMessageDialog::Open( - EAppMsgType::Ok, LOCTEXT("ThirdPartyLibraryError", "Failed to load discord-rpc library")); - } -} - -void FdiscordrpcModule::ShutdownModule() -{ - // This function may be called during shutdown to clean up your module. For modules that - // support dynamic reloading, - // we call this function before unloading the module. - - // Free the dll handle - FPlatformProcess::FreeDllHandle(DiscordLibraryHandle); - DiscordLibraryHandle = nullptr; -} - -#undef LOCTEXT_NAMESPACE - -IMPLEMENT_MODULE(FdiscordrpcModule, discordrpc) \ No newline at end of file diff --git a/examples/unrealstatus/Plugins/discordrpc/Source/discordrpc/Public/discordrpc.h b/examples/unrealstatus/Plugins/discordrpc/Source/discordrpc/Public/discordrpc.h deleted file mode 100644 index 8a9323c..0000000 --- a/examples/unrealstatus/Plugins/discordrpc/Source/discordrpc/Public/discordrpc.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. - -#pragma once - -#include "ModuleManager.h" - -class FdiscordrpcModule : public IModuleInterface { -public: - /** IModuleInterface implementation */ - virtual void StartupModule() override; - virtual void ShutdownModule() override; - -private: - /** Handle to the test dll we will load */ - void* DiscordLibraryHandle; -}; \ No newline at end of file diff --git a/examples/unrealstatus/Plugins/discordrpc/Source/discordrpc/discordrpc.Build.cs b/examples/unrealstatus/Plugins/discordrpc/Source/discordrpc/discordrpc.Build.cs deleted file mode 100644 index d34e809..0000000 --- a/examples/unrealstatus/Plugins/discordrpc/Source/discordrpc/discordrpc.Build.cs +++ /dev/null @@ -1,65 +0,0 @@ -// Copyright 1998-2017 Epic Games, Inc. All Rights Reserved. - -using UnrealBuildTool; - -public class discordrpc : ModuleRules -{ - public discordrpc(ReadOnlyTargetRules Target) : base(Target) - { - Definitions.Add("DISCORD_DYNAMIC_LIB=1"); - PCHUsage = ModuleRules.PCHUsageMode.UseExplicitOrSharedPCHs; - - PublicIncludePaths.AddRange( - new string[] { - "discordrpc/Public" - // ... add public include paths required here ... - } - ); - - - PrivateIncludePaths.AddRange( - new string[] { - "discordrpc/Private", - "../../../../../include" - // ... add other private include paths required here ... - } - ); - - PublicLibraryPaths.AddRange( - new string[] { - System.IO.Path.Combine(ModuleDirectory, "../../Binaries/ThirdParty/discordrpcLibrary/", Target.Platform.ToString()), - } - ); - - - PublicDependencyModuleNames.AddRange( - new string[] - { - "CoreUObject", - "Engine", - "Slate", - "SlateCore", - "Core", - "discordrpcLibrary", - "Projects" - // ... add other public dependencies that you statically link with here ... - } - ); - - - PrivateDependencyModuleNames.AddRange( - new string[] - { - // ... add private dependencies that you statically link with here ... - } - ); - - - DynamicallyLoadedModuleNames.AddRange( - new string[] - { - // ... add any modules that your module loads dynamically here ... - } - ); - } -}