Compare commits

..

7 Commits

Author SHA1 Message Date
Mason Sciotti
963aa9f3e5
[Maintenance PR for Legacy Gamedevs] Add party privacy enum (#306)
* Add party privacy enum

* Add party privacy enum

* Possible unreal working

* Cast to int
2020-09-21 14:51:48 -07:00
msciotti
e4c0c569ec
Clarify deprecation 2019-11-27 11:26:13 -08:00
IceNinjaman
b6d0a9cdbd wchar.h instead cwchar when compiler is MinGW to prevent weird behavior with vsnwprintf (#277) 2019-11-27 11:24:32 -08:00
msciotti
eff23a770a
add deprecation note to readme 2019-07-10 14:39:38 -07:00
Kenny McCormick
34ce3ac803 fix "destopFileFormat" typo (#283)
resolution for #282
2019-04-30 11:39:14 -07:00
msciotti
c59fd6df20
Revert "Choose pipe number on initialize (#250)"
This reverts commit 4824b20f28b1ebffb2a57881684ef87f76659a6c.
2019-01-24 13:23:35 -08:00
Mason Sciotti
4824b20f28
Choose pipe number on initialize (#250)
* Choose pipe number on initialize

* Get pipe from base connection instance

* UE4 support

* Warnings as errors yelling

* Fix windows connection

* Oops all variables

* maybe this fixes it

* This one actually works!!!!

* Fix double function declaration
2019-01-14 00:16:22 -08:00
16 changed files with 66 additions and 29 deletions

View File

@ -1,5 +1,11 @@
# Discord RPC
## Deprecation Notice
This library has been deprecated in favor of Discord's GameSDK. [Learn more here](https://discordapp.com/developers/docs/game-sdk/sdk-starter-guide)
---
This is a library for interfacing your game with a locally running Discord desktop client. It's known to work on Windows, macOS, and Linux. You can use the lib directly if you like, or use it as a guide to writing your own if it doesn't suit your game as is. PRs/feedback welcome if you have an improvement everyone might want, or can describe how this doesn't meet your needs.
Included here are some quick demos that implement the very minimal subset to show current status, and

View File

@ -31,6 +31,11 @@ public class DiscordController : MonoBehaviour
clickCounter++;
presence.details = string.Format("Button clicked {0} times", clickCounter);
presence.joinSecret = "aSecret";
presence.partyId = "aPartyId";
presence.partySize = 1;
presence.partyMax = 3;
presence.partyPrivacy = DiscordRpc.PartyPrivacy.Public;
DiscordRpc.UpdatePresence(presence);
}

View File

@ -56,6 +56,7 @@ public class DiscordRpc
public IntPtr partyId; /* max 128 bytes */
public int partySize;
public int partyMax;
public int partyPrivacy;
public IntPtr matchSecret; /* max 128 bytes */
public IntPtr joinSecret; /* max 128 bytes */
public IntPtr spectateSecret; /* max 128 bytes */
@ -78,7 +79,13 @@ public class DiscordRpc
Ignore = 2
}
public static void Initialize(string applicationId, ref EventHandlers handlers, bool autoRegister, string optionalSteamId, int pipe = 0)
public enum PartyPrivacy
{
Private = 0,
Public = 1
}
public static void Initialize(string applicationId, ref EventHandlers handlers, bool autoRegister, string optionalSteamId)
{
Callbacks = handlers;
@ -90,11 +97,11 @@ public class DiscordRpc
staticEventHandlers.spectateCallback += DiscordRpc.SpectateCallback;
staticEventHandlers.requestCallback += DiscordRpc.RequestCallback;
InitializeInternal(applicationId, ref staticEventHandlers, autoRegister, optionalSteamId, pipe);
InitializeInternal(applicationId, ref staticEventHandlers, autoRegister, optionalSteamId);
}
[DllImport("discord-rpc", EntryPoint = "Discord_Initialize", CallingConvention = CallingConvention.Cdecl)]
static extern void InitializeInternal(string applicationId, ref EventHandlers handlers, bool autoRegister, string optionalSteamId, int pipe);
static extern void InitializeInternal(string applicationId, ref EventHandlers handlers, bool autoRegister, string optionalSteamId);
[DllImport("discord-rpc", EntryPoint = "Discord_Shutdown", CallingConvention = CallingConvention.Cdecl)]
public static extern void Shutdown();
@ -137,6 +144,7 @@ public class DiscordRpc
public string partyId; /* max 128 bytes */
public int partySize;
public int partyMax;
public PartyPrivacy partyPrivacy;
public string matchSecret; /* max 128 bytes */
public string joinSecret; /* max 128 bytes */
public string spectateSecret; /* max 128 bytes */
@ -164,6 +172,7 @@ public class DiscordRpc
_presence.partyId = StrToPtr(partyId);
_presence.partySize = partySize;
_presence.partyMax = partyMax;
_presence.partyPrivacy = (int)partyPrivacy;
_presence.matchSecret = StrToPtr(matchSecret);
_presence.joinSecret = StrToPtr(joinSecret);
_presence.spectateSecret = StrToPtr(spectateSecret);

View File

@ -47,6 +47,7 @@ static void updateDiscordPresence()
discordPresence.partyId = "party1234";
discordPresence.partySize = 1;
discordPresence.partyMax = 6;
discordPresence.partyPrivacy = DISCORD_PARTY_PUBLIC;
discordPresence.matchSecret = "xyzzy";
discordPresence.joinSecret = "join";
discordPresence.spectateSecret = "look";
@ -129,7 +130,7 @@ static void discordInit()
handlers.joinGame = handleDiscordJoin;
handlers.spectateGame = handleDiscordSpectate;
handlers.joinRequest = handleDiscordJoinRequest;
Discord_Initialize(APPLICATION_ID, &handlers, 1, NULL, 0);
Discord_Initialize(APPLICATION_ID, &handlers, 1, NULL);
}
static void gameLoop()

View File

@ -82,8 +82,7 @@ static void JoinRequestHandler(const DiscordUser* request)
void UDiscordRpc::Initialize(const FString& applicationId,
bool autoRegister,
const FString& optionalSteamId,
int pipe)
const FString& optionalSteamId)
{
self = this;
IsConnected = false;
@ -103,7 +102,7 @@ void UDiscordRpc::Initialize(const FString& applicationId,
auto appId = StringCast<ANSICHAR>(*applicationId);
auto steamId = StringCast<ANSICHAR>(*optionalSteamId);
Discord_Initialize(
(const char*)appId.Get(), &handlers, autoRegister, (const char*)steamId.Get(), pipe);
(const char*)appId.Get(), &handlers, autoRegister, (const char*)steamId.Get());
}
void UDiscordRpc::Shutdown()
@ -154,6 +153,7 @@ void UDiscordRpc::UpdatePresence()
rp.endTimestamp = RichPresence.endTimestamp;
rp.partySize = RichPresence.partySize;
rp.partyMax = RichPresence.partyMax;
rp.partyPrivacy = (int)RichPresence.partyPrivacy;
rp.instance = RichPresence.instance;
Discord_UpdatePresence(&rp);

View File

@ -35,6 +35,16 @@ enum class EDiscordJoinResponseCodes : uint8
DISCORD_REPLY_IGNORE UMETA(DisplayName="Ignore")
};
/**
* Valid party privacy values
*/
UENUM(BlueprintType)
enum class EDiscordPartyPrivacy: uint8
{
DISCORD_PARTY_PRIVATE UMETA(DisplayName="Private"),
DISCORD_PARTY_PUBLIC UMETA(DisplayName="Public")
};
DECLARE_LOG_CATEGORY_EXTERN(Discord, Log, All);
DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FDiscordConnected, const FDiscordUserData&, joinRequest);
@ -77,6 +87,8 @@ struct FDiscordRichPresence {
UPROPERTY(BlueprintReadWrite)
int partyMax;
UPROPERTY(BlueprintReadWrite)
EDiscordPartyPrivacy partyPrivacy;
UPROPERTY(BlueprintReadWrite)
FString matchSecret;
UPROPERTY(BlueprintReadWrite)
FString joinSecret;
@ -99,8 +111,7 @@ public:
Category = "Discord")
void Initialize(const FString& applicationId,
bool autoRegister,
const FString& optionalSteamId,
int optionalPipeNumber);
const FString& optionalSteamId);
UFUNCTION(BlueprintCallable,
meta = (DisplayName = "Shut down connection", Keywords = "Discord rpc"),

View File

@ -35,6 +35,7 @@ typedef struct DiscordRichPresence {
const char* partyId; /* max 128 bytes */
int partySize;
int partyMax;
int partyPrivacy;
const char* matchSecret; /* max 128 bytes */
const char* joinSecret; /* max 128 bytes */
const char* spectateSecret; /* max 128 bytes */
@ -60,12 +61,13 @@ typedef struct DiscordEventHandlers {
#define DISCORD_REPLY_NO 0
#define DISCORD_REPLY_YES 1
#define DISCORD_REPLY_IGNORE 2
#define DISCORD_PARTY_PRIVATE 0
#define DISCORD_PARTY_PUBLIC 1
DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
DiscordEventHandlers* handlers,
int autoRegister,
const char* optionalSteamId,
int optionalPipeNumber);
const char* optionalSteamId);
DISCORD_EXPORT void Discord_Shutdown(void);
/* checks for incoming messages, dispatches callbacks */

View File

@ -12,7 +12,7 @@ struct BaseConnection {
static BaseConnection* Create();
static void Destroy(BaseConnection*&);
bool isOpen{false};
bool Open(int pipe);
bool Open();
bool Close();
bool Write(const void* data, size_t length);
bool Read(void* data, size_t length);

View File

@ -49,7 +49,7 @@ static const char* GetTempPath()
c = nullptr;
}
bool BaseConnection::Open(int pipe)
bool BaseConnection::Open()
{
const char* tempPath = GetTempPath();
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
@ -62,7 +62,8 @@ bool BaseConnection::Open(int pipe)
int optval = 1;
setsockopt(self->sock, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval));
#endif
for (int pipeNum = pipe; pipeNum < 10; ++pipeNum) {
for (int pipeNum = 0; pipeNum < 10; ++pipeNum) {
snprintf(
PipeAddr.sun_path, sizeof(PipeAddr.sun_path), "%s/discord-ipc-%d", tempPath, pipeNum);
int err = connect(self->sock, (const sockaddr*)&PipeAddr, sizeof(PipeAddr));

View File

@ -6,7 +6,6 @@
#define NOIME
#include <assert.h>
#include <windows.h>
#include <sstream>
int GetProcessId()
{
@ -31,11 +30,11 @@ static BaseConnectionWin Connection;
c = nullptr;
}
bool BaseConnection::Open(int pipe)
bool BaseConnection::Open()
{
wchar_t pipeName[]{L"\\\\?\\pipe\\discord-ipc-0"};
const size_t pipeDigit = sizeof(pipeName) / sizeof(wchar_t) - 2;
pipeName[pipeDigit] += pipe;
pipeName[pipeDigit] = L'0';
auto self = reinterpret_cast<BaseConnectionWin*>(this);
for (;;) {
self->pipe = ::CreateFileW(

View File

@ -41,7 +41,7 @@ extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const
command = exePath;
}
const char* destopFileFormat = "[Desktop Entry]\n"
const char* desktopFileFormat = "[Desktop Entry]\n"
"Name=Game %s\n"
"Exec=%s %%u\n" // note: it really wants that %u in there
"Type=Application\n"
@ -50,7 +50,7 @@ extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const
"MimeType=x-scheme-handler/discord-%s;\n";
char desktopFile[2048];
int fileLen = snprintf(
desktopFile, sizeof(desktopFile), destopFileFormat, applicationId, command, applicationId);
desktopFile, sizeof(desktopFile), desktopFileFormat, applicationId, command, applicationId);
if (fileLen <= 0) {
return;
}

View File

@ -7,7 +7,6 @@
#define NOIME
#include <windows.h>
#include <psapi.h>
#include <cwchar>
#include <cstdio>
/**
@ -20,6 +19,7 @@
* The entire function is rewritten
*/
#ifdef __MINGW32__
#include <wchar.h>
/// strsafe.h fixes
static HRESULT StringCbPrintfW(LPWSTR pszDest, size_t cbDest, LPCWSTR pszFormat, ...)
{
@ -34,6 +34,7 @@ static HRESULT StringCbPrintfW(LPWSTR pszDest, size_t cbDest, LPCWSTR pszFormat,
return ret;
}
#else
#include <cwchar>
#include <strsafe.h>
#endif // __MINGW32__

View File

@ -273,8 +273,7 @@ static bool DeregisterForEvent(const char* evtName)
extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
DiscordEventHandlers* handlers,
int autoRegister,
const char* optionalSteamId,
int pipe)
const char* optionalSteamId)
{
IoThread = new (std::nothrow) IoThreadHolder();
if (IoThread == nullptr) {
@ -309,7 +308,7 @@ extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
return;
}
Connection = RpcConnection::Create(applicationId, pipe);
Connection = RpcConnection::Create(applicationId);
Connection->onConnect = [](JsonDocument& readyMessage) {
Discord_UpdateHandlers(&QueuedHandlers);
if (QueuedPresence.length > 0) {

View File

@ -6,11 +6,10 @@
static const int RpcVersion = 1;
static RpcConnection Instance;
/*static*/ RpcConnection* RpcConnection::Create(const char* applicationId, int pipe)
/*static*/ RpcConnection* RpcConnection::Create(const char* applicationId)
{
Instance.connection = BaseConnection::Create();
StringCopy(Instance.appId, applicationId);
Instance.pipe = pipe;
return &Instance;
}
@ -27,7 +26,7 @@ void RpcConnection::Open()
return;
}
if (state == State::Disconnected && !connection->Open(Instance.pipe)) {
if (state == State::Disconnected && !connection->Open()) {
return;
}

View File

@ -43,12 +43,11 @@ struct RpcConnection {
void (*onConnect)(JsonDocument& message){nullptr};
void (*onDisconnect)(int errorCode, const char* message){nullptr};
char appId[64]{};
int pipe;
int lastErrorCode{0};
char lastErrorMessage[256]{};
RpcConnection::MessageFrame sendFrame;
static RpcConnection* Create(const char* applicationId, int pipe);
static RpcConnection* Create(const char* applicationId);
static void Destroy(RpcConnection*&);
inline bool IsOpen() const { return state == State::Connected; }

View File

@ -134,7 +134,7 @@ size_t JsonWriteRichPresenceObj(char* dest,
}
if ((presence->partyId && presence->partyId[0]) || presence->partySize ||
presence->partyMax) {
presence->partyMax || presence->partyPrivacy) {
WriteObject party(writer, "party");
WriteOptionalString(writer, "id", presence->partyId);
if (presence->partySize && presence->partyMax) {
@ -142,6 +142,11 @@ size_t JsonWriteRichPresenceObj(char* dest,
writer.Int(presence->partySize);
writer.Int(presence->partyMax);
}
if (presence->partyPrivacy) {
WriteKey(writer, "privacy");
writer.Int(presence->partyPrivacy);
}
}
if ((presence->matchSecret && presence->matchSecret[0]) ||