Compare commits
9 Commits
master
...
choose-pip
Author | SHA1 | Date | |
---|---|---|---|
|
8bb85f0545 | ||
|
766596722c | ||
|
7fe88765fd | ||
|
1d30b94987 | ||
|
6796d2ffa9 | ||
|
d90a8efd47 | ||
|
544f91a5a8 | ||
|
2f52c24f6d | ||
|
d5a342c7bb |
@ -1,11 +1,5 @@
|
||||
# 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
|
||||
|
@ -31,11 +31,6 @@ 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);
|
||||
}
|
||||
|
@ -56,7 +56,6 @@ 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 */
|
||||
@ -79,13 +78,7 @@ public class DiscordRpc
|
||||
Ignore = 2
|
||||
}
|
||||
|
||||
public enum PartyPrivacy
|
||||
{
|
||||
Private = 0,
|
||||
Public = 1
|
||||
}
|
||||
|
||||
public static void Initialize(string applicationId, ref EventHandlers handlers, bool autoRegister, string optionalSteamId)
|
||||
public static void Initialize(string applicationId, ref EventHandlers handlers, bool autoRegister, string optionalSteamId, int pipe = 0)
|
||||
{
|
||||
Callbacks = handlers;
|
||||
|
||||
@ -97,11 +90,11 @@ public class DiscordRpc
|
||||
staticEventHandlers.spectateCallback += DiscordRpc.SpectateCallback;
|
||||
staticEventHandlers.requestCallback += DiscordRpc.RequestCallback;
|
||||
|
||||
InitializeInternal(applicationId, ref staticEventHandlers, autoRegister, optionalSteamId);
|
||||
InitializeInternal(applicationId, ref staticEventHandlers, autoRegister, optionalSteamId, pipe);
|
||||
}
|
||||
|
||||
[DllImport("discord-rpc", EntryPoint = "Discord_Initialize", CallingConvention = CallingConvention.Cdecl)]
|
||||
static extern void InitializeInternal(string applicationId, ref EventHandlers handlers, bool autoRegister, string optionalSteamId);
|
||||
static extern void InitializeInternal(string applicationId, ref EventHandlers handlers, bool autoRegister, string optionalSteamId, int pipe);
|
||||
|
||||
[DllImport("discord-rpc", EntryPoint = "Discord_Shutdown", CallingConvention = CallingConvention.Cdecl)]
|
||||
public static extern void Shutdown();
|
||||
@ -144,7 +137,6 @@ 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 */
|
||||
@ -172,7 +164,6 @@ 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);
|
||||
|
@ -47,7 +47,6 @@ 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";
|
||||
@ -130,7 +129,7 @@ static void discordInit()
|
||||
handlers.joinGame = handleDiscordJoin;
|
||||
handlers.spectateGame = handleDiscordSpectate;
|
||||
handlers.joinRequest = handleDiscordJoinRequest;
|
||||
Discord_Initialize(APPLICATION_ID, &handlers, 1, NULL);
|
||||
Discord_Initialize(APPLICATION_ID, &handlers, 1, NULL, 0);
|
||||
}
|
||||
|
||||
static void gameLoop()
|
||||
|
@ -82,7 +82,8 @@ static void JoinRequestHandler(const DiscordUser* request)
|
||||
|
||||
void UDiscordRpc::Initialize(const FString& applicationId,
|
||||
bool autoRegister,
|
||||
const FString& optionalSteamId)
|
||||
const FString& optionalSteamId,
|
||||
int pipe)
|
||||
{
|
||||
self = this;
|
||||
IsConnected = false;
|
||||
@ -102,7 +103,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());
|
||||
(const char*)appId.Get(), &handlers, autoRegister, (const char*)steamId.Get(), pipe);
|
||||
}
|
||||
|
||||
void UDiscordRpc::Shutdown()
|
||||
@ -153,7 +154,6 @@ 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);
|
||||
|
@ -35,16 +35,6 @@ 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);
|
||||
@ -87,8 +77,6 @@ struct FDiscordRichPresence {
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
int partyMax;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
EDiscordPartyPrivacy partyPrivacy;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
FString matchSecret;
|
||||
UPROPERTY(BlueprintReadWrite)
|
||||
FString joinSecret;
|
||||
@ -111,7 +99,8 @@ public:
|
||||
Category = "Discord")
|
||||
void Initialize(const FString& applicationId,
|
||||
bool autoRegister,
|
||||
const FString& optionalSteamId);
|
||||
const FString& optionalSteamId,
|
||||
int optionalPipeNumber);
|
||||
|
||||
UFUNCTION(BlueprintCallable,
|
||||
meta = (DisplayName = "Shut down connection", Keywords = "Discord rpc"),
|
||||
|
@ -35,7 +35,6 @@ 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 */
|
||||
@ -61,13 +60,12 @@ 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);
|
||||
const char* optionalSteamId,
|
||||
int optionalPipeNumber);
|
||||
DISCORD_EXPORT void Discord_Shutdown(void);
|
||||
|
||||
/* checks for incoming messages, dispatches callbacks */
|
||||
|
@ -12,7 +12,7 @@ struct BaseConnection {
|
||||
static BaseConnection* Create();
|
||||
static void Destroy(BaseConnection*&);
|
||||
bool isOpen{false};
|
||||
bool Open();
|
||||
bool Open(int pipe);
|
||||
bool Close();
|
||||
bool Write(const void* data, size_t length);
|
||||
bool Read(void* data, size_t length);
|
||||
|
@ -49,7 +49,7 @@ static const char* GetTempPath()
|
||||
c = nullptr;
|
||||
}
|
||||
|
||||
bool BaseConnection::Open()
|
||||
bool BaseConnection::Open(int pipe)
|
||||
{
|
||||
const char* tempPath = GetTempPath();
|
||||
auto self = reinterpret_cast<BaseConnectionUnix*>(this);
|
||||
@ -62,8 +62,7 @@ bool BaseConnection::Open()
|
||||
int optval = 1;
|
||||
setsockopt(self->sock, SOL_SOCKET, SO_NOSIGPIPE, &optval, sizeof(optval));
|
||||
#endif
|
||||
|
||||
for (int pipeNum = 0; pipeNum < 10; ++pipeNum) {
|
||||
for (int pipeNum = pipe; 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));
|
||||
|
@ -6,6 +6,7 @@
|
||||
#define NOIME
|
||||
#include <assert.h>
|
||||
#include <windows.h>
|
||||
#include <sstream>
|
||||
|
||||
int GetProcessId()
|
||||
{
|
||||
@ -30,11 +31,11 @@ static BaseConnectionWin Connection;
|
||||
c = nullptr;
|
||||
}
|
||||
|
||||
bool BaseConnection::Open()
|
||||
bool BaseConnection::Open(int pipe)
|
||||
{
|
||||
wchar_t pipeName[]{L"\\\\?\\pipe\\discord-ipc-0"};
|
||||
const size_t pipeDigit = sizeof(pipeName) / sizeof(wchar_t) - 2;
|
||||
pipeName[pipeDigit] = L'0';
|
||||
pipeName[pipeDigit] += pipe;
|
||||
auto self = reinterpret_cast<BaseConnectionWin*>(this);
|
||||
for (;;) {
|
||||
self->pipe = ::CreateFileW(
|
||||
|
@ -41,7 +41,7 @@ extern "C" DISCORD_EXPORT void Discord_Register(const char* applicationId, const
|
||||
command = exePath;
|
||||
}
|
||||
|
||||
const char* desktopFileFormat = "[Desktop Entry]\n"
|
||||
const char* destopFileFormat = "[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), desktopFileFormat, applicationId, command, applicationId);
|
||||
desktopFile, sizeof(desktopFile), destopFileFormat, applicationId, command, applicationId);
|
||||
if (fileLen <= 0) {
|
||||
return;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
#define NOIME
|
||||
#include <windows.h>
|
||||
#include <psapi.h>
|
||||
#include <cwchar>
|
||||
#include <cstdio>
|
||||
|
||||
/**
|
||||
@ -19,7 +20,6 @@
|
||||
* The entire function is rewritten
|
||||
*/
|
||||
#ifdef __MINGW32__
|
||||
#include <wchar.h>
|
||||
/// strsafe.h fixes
|
||||
static HRESULT StringCbPrintfW(LPWSTR pszDest, size_t cbDest, LPCWSTR pszFormat, ...)
|
||||
{
|
||||
@ -34,7 +34,6 @@ static HRESULT StringCbPrintfW(LPWSTR pszDest, size_t cbDest, LPCWSTR pszFormat,
|
||||
return ret;
|
||||
}
|
||||
#else
|
||||
#include <cwchar>
|
||||
#include <strsafe.h>
|
||||
#endif // __MINGW32__
|
||||
|
||||
|
@ -273,7 +273,8 @@ static bool DeregisterForEvent(const char* evtName)
|
||||
extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
|
||||
DiscordEventHandlers* handlers,
|
||||
int autoRegister,
|
||||
const char* optionalSteamId)
|
||||
const char* optionalSteamId,
|
||||
int pipe)
|
||||
{
|
||||
IoThread = new (std::nothrow) IoThreadHolder();
|
||||
if (IoThread == nullptr) {
|
||||
@ -308,7 +309,7 @@ extern "C" DISCORD_EXPORT void Discord_Initialize(const char* applicationId,
|
||||
return;
|
||||
}
|
||||
|
||||
Connection = RpcConnection::Create(applicationId);
|
||||
Connection = RpcConnection::Create(applicationId, pipe);
|
||||
Connection->onConnect = [](JsonDocument& readyMessage) {
|
||||
Discord_UpdateHandlers(&QueuedHandlers);
|
||||
if (QueuedPresence.length > 0) {
|
||||
|
@ -6,10 +6,11 @@
|
||||
static const int RpcVersion = 1;
|
||||
static RpcConnection Instance;
|
||||
|
||||
/*static*/ RpcConnection* RpcConnection::Create(const char* applicationId)
|
||||
/*static*/ RpcConnection* RpcConnection::Create(const char* applicationId, int pipe)
|
||||
{
|
||||
Instance.connection = BaseConnection::Create();
|
||||
StringCopy(Instance.appId, applicationId);
|
||||
Instance.pipe = pipe;
|
||||
return &Instance;
|
||||
}
|
||||
|
||||
@ -26,7 +27,7 @@ void RpcConnection::Open()
|
||||
return;
|
||||
}
|
||||
|
||||
if (state == State::Disconnected && !connection->Open()) {
|
||||
if (state == State::Disconnected && !connection->Open(Instance.pipe)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -43,11 +43,12 @@ 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);
|
||||
static RpcConnection* Create(const char* applicationId, int pipe);
|
||||
static void Destroy(RpcConnection*&);
|
||||
|
||||
inline bool IsOpen() const { return state == State::Connected; }
|
||||
|
@ -134,7 +134,7 @@ size_t JsonWriteRichPresenceObj(char* dest,
|
||||
}
|
||||
|
||||
if ((presence->partyId && presence->partyId[0]) || presence->partySize ||
|
||||
presence->partyMax || presence->partyPrivacy) {
|
||||
presence->partyMax) {
|
||||
WriteObject party(writer, "party");
|
||||
WriteOptionalString(writer, "id", presence->partyId);
|
||||
if (presence->partySize && presence->partyMax) {
|
||||
@ -142,11 +142,6 @@ 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]) ||
|
||||
|
Loading…
x
Reference in New Issue
Block a user