From 26a905b4f82a920915b48acb15fc9819b02ead63 Mon Sep 17 00:00:00 2001 From: Xpl0itR Date: Wed, 22 May 2019 15:18:57 +0100 Subject: [PATCH] Big update Switched from using the official discord rpc library that requires downloading a dll/so to using discord-rpc-csharp --- Ryujinx/DiscordRpc.cs | 241 ----------------------- Ryujinx/Program.cs | 57 +++--- Ryujinx/{RPsupported => RPsupported.dat} | 0 Ryujinx/Ryujinx.csproj | 3 +- 4 files changed, 32 insertions(+), 269 deletions(-) delete mode 100644 Ryujinx/DiscordRpc.cs rename Ryujinx/{RPsupported => RPsupported.dat} (100%) diff --git a/Ryujinx/DiscordRpc.cs b/Ryujinx/DiscordRpc.cs deleted file mode 100644 index 9be4f80ecd..0000000000 --- a/Ryujinx/DiscordRpc.cs +++ /dev/null @@ -1,241 +0,0 @@ -/* -Copyright 2017 Discord, Inc. - -Permission is hereby granted, free of charge, to any person obtaining a copy of -this software and associated documentation files (the "Software"), to deal in -the Software without restriction, including without limitation the rights to -use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies -of the Software, and to permit persons to whom the Software is furnished to do -so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ -using System; -using System.Collections.Generic; -using System.Runtime.InteropServices; -using System.Text; - -public class DiscordRpc -{ - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void ReadyCallback(ref DiscordUser connectedUser); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void DisconnectedCallback(int errorCode, string message); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void ErrorCallback(int errorCode, string message); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void JoinCallback(string secret); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void SpectateCallback(string secret); - - [UnmanagedFunctionPointer(CallingConvention.Cdecl)] - public delegate void RequestCallback(ref DiscordUser request); - - public struct EventHandlers - { - public ReadyCallback readyCallback; - public DisconnectedCallback disconnectedCallback; - public ErrorCallback errorCallback; - public JoinCallback joinCallback; - public SpectateCallback spectateCallback; - public RequestCallback requestCallback; - } - - [Serializable, StructLayout(LayoutKind.Sequential)] - public struct RichPresenceStruct - { - public IntPtr state; /* max 128 bytes */ - public IntPtr details; /* max 128 bytes */ - public long startTimestamp; - public long endTimestamp; - public IntPtr largeImageKey; /* max 64 bytes */ - public IntPtr largeImageText; /* max 128 bytes */ - public IntPtr smallImageKey; /* max 32 bytes */ - public IntPtr smallImageText; /* max 128 bytes */ - public IntPtr partyId; /* max 128 bytes */ - public int partySize; - public int partyMax; - public IntPtr matchSecret; /* max 128 bytes */ - public IntPtr joinSecret; /* max 128 bytes */ - public IntPtr spectateSecret; /* max 128 bytes */ - public bool instance; - } - - [Serializable] - public struct DiscordUser - { - public string userId; - public string username; - public string discriminator; - public string avatar; - } - - public enum Reply - { - No = 0, - Yes = 1, - Ignore = 2 - } - - [DllImport("discord-rpc", EntryPoint = "Discord_Initialize", CallingConvention = CallingConvention.Cdecl)] - public static extern void Initialize(string applicationId, ref EventHandlers handlers, bool autoRegister, string optionalSteamId); - - [DllImport("discord-rpc", EntryPoint = "Discord_Shutdown", CallingConvention = CallingConvention.Cdecl)] - public static extern void Shutdown(); - - [DllImport("discord-rpc", EntryPoint = "Discord_RunCallbacks", CallingConvention = CallingConvention.Cdecl)] - public static extern void RunCallbacks(); - - [DllImport("discord-rpc", EntryPoint = "Discord_UpdatePresence", CallingConvention = CallingConvention.Cdecl)] - private static extern void UpdatePresenceNative(ref RichPresenceStruct presence); - - [DllImport("discord-rpc", EntryPoint = "Discord_ClearPresence", CallingConvention = CallingConvention.Cdecl)] - public static extern void ClearPresence(); - - [DllImport("discord-rpc", EntryPoint = "Discord_Respond", CallingConvention = CallingConvention.Cdecl)] - public static extern void Respond(string userId, Reply reply); - - [DllImport("discord-rpc", EntryPoint = "Discord_UpdateHandlers", CallingConvention = CallingConvention.Cdecl)] - public static extern void UpdateHandlers(ref EventHandlers handlers); - - public static void UpdatePresence(RichPresence presence) - { - var presencestruct = presence.GetStruct(); - UpdatePresenceNative(ref presencestruct); - presence.FreeMem(); - } - - public class RichPresence - { - private RichPresenceStruct _presence; - private readonly List _buffers = new List(10); - - public string state; /* max 128 bytes */ - public string details; /* max 128 bytes */ - public long startTimestamp; - public long endTimestamp; - public string largeImageKey; /* max 64 bytes */ - public string largeImageText; /* max 128 bytes */ - public string smallImageKey; /* max 32 bytes */ - public string smallImageText; /* max 128 bytes */ - public string partyId; /* max 128 bytes */ - public int partySize; - public int partyMax; - public string matchSecret; /* max 128 bytes */ - public string joinSecret; /* max 128 bytes */ - public string spectateSecret; /* max 128 bytes */ - public bool instance; - - /// - /// Get the reprensentation of this instance - /// - /// reprensentation of this instance - internal RichPresenceStruct GetStruct() - { - if (_buffers.Count > 0) - { - FreeMem(); - } - - _presence.state = StrToPtr(state, 128); - _presence.details = StrToPtr(details, 128); - _presence.startTimestamp = startTimestamp; - _presence.endTimestamp = endTimestamp; - _presence.largeImageKey = StrToPtr(largeImageKey, 64); - _presence.largeImageText = StrToPtr(largeImageText, 128); - _presence.smallImageKey = StrToPtr(smallImageKey, 32); - _presence.smallImageText = StrToPtr(smallImageText, 128); - _presence.partyId = StrToPtr(partyId, 128); - _presence.partySize = partySize; - _presence.partyMax = partyMax; - _presence.matchSecret = StrToPtr(matchSecret, 128); - _presence.joinSecret = StrToPtr(joinSecret, 128); - _presence.spectateSecret = StrToPtr(spectateSecret, 128); - _presence.instance = instance; - - return _presence; - } - - /// - /// Returns a pointer to a representation of the given string with a size of maxbytes - /// - /// String to convert - /// Max number of bytes to use - /// Pointer to the UTF-8 representation of - private IntPtr StrToPtr(string input, int maxbytes) - { - if (string.IsNullOrEmpty(input)) return IntPtr.Zero; - var convstr = StrClampBytes(input, maxbytes); - var convbytecnt = Encoding.UTF8.GetByteCount(convstr); - var buffer = Marshal.AllocHGlobal(convbytecnt); - _buffers.Add(buffer); - Marshal.Copy(Encoding.UTF8.GetBytes(convstr), 0, buffer, convbytecnt); - return buffer; - } - - /// - /// Convert string to UTF-8 and add null termination - /// - /// string to convert - /// UTF-8 representation of with added null termination - private static string StrToUtf8NullTerm(string toconv) - { - var str = toconv.Trim(); - var bytes = Encoding.Default.GetBytes(str); - if (bytes.Length > 0 && bytes[bytes.Length - 1] != 0) - { - str += "\0\0"; - } - return Encoding.UTF8.GetString(Encoding.UTF8.GetBytes(str)); - } - - /// - /// Clamp the string to the given byte length preserving null termination - /// - /// string to clamp - /// max bytes the resulting string should have (including null termination) - /// null terminated string with a byte length less or equal to - private static string StrClampBytes(string toclamp, int maxbytes) - { - var str = StrToUtf8NullTerm(toclamp); - var strbytes = Encoding.UTF8.GetBytes(str); - - if (strbytes.Length <= maxbytes) - { - return str; - } - - var newstrbytes = new byte[] { }; - Array.Copy(strbytes, 0, newstrbytes, 0, maxbytes - 1); - newstrbytes[newstrbytes.Length - 1] = 0; - newstrbytes[newstrbytes.Length - 2] = 0; - - return Encoding.UTF8.GetString(newstrbytes); - } - - /// - /// Free the allocated memory for conversion to - /// - internal void FreeMem() - { - for (var i = _buffers.Count - 1; i >= 0; i--) - { - Marshal.FreeHGlobal(_buffers[i]); - _buffers.RemoveAt(i); - } - } - } -} \ No newline at end of file diff --git a/Ryujinx/Program.cs b/Ryujinx/Program.cs index cfa2511faa..29fea9a8cf 100644 --- a/Ryujinx/Program.cs +++ b/Ryujinx/Program.cs @@ -11,9 +11,9 @@ namespace Ryujinx { class Program { - private static DiscordRpc.RichPresence Presence; + public static DiscordRPC.DiscordRpcClient DiscordClient; - private static DiscordRpc.EventHandlers Handlers; + public static DiscordRPC.RichPresence DiscordPresence; public static string ApplicationDirectory => AppDomain.CurrentDomain.BaseDirectory; @@ -21,18 +21,18 @@ namespace Ryujinx { Console.Title = "Ryujinx Console"; - if (File.Exists("./discord-rpc.dll") || File.Exists("./discord-rpc.so")) - { - Handlers = new DiscordRpc.EventHandlers(); - Presence = new DiscordRpc.RichPresence(); - DiscordRpc.Initialize("568815339807309834", ref Handlers, true, null); - Presence.details = "Ryujinx Console"; - Presence.state = "Reading the console logs..."; - Presence.startTimestamp = DateTimeOffset.Now.ToUnixTimeSeconds(); - Presence.largeImageKey = "ryujinx"; - Presence.largeImageText = "Ryujinx"; - DiscordRpc.UpdatePresence(Presence); - } + DiscordClient = new DiscordRPC.DiscordRpcClient("568815339807309834"); + DiscordPresence = new DiscordRPC.RichPresence(); + DiscordPresence.Assets = new DiscordRPC.Assets(); + DiscordPresence.Timestamps = new DiscordRPC.Timestamps(DateTime.UtcNow); + + DiscordPresence.Details = "Ryujinx Console"; + DiscordPresence.State = "Reading the console logs..."; + DiscordPresence.Assets.LargeImageKey = "ryujinx"; + DiscordPresence.Assets.LargeImageText = "Ryujinx"; + + DiscordClient.Initialize(); + DiscordClient.SetPresence(DiscordPresence); IGalRenderer renderer = new OglRenderer(); @@ -117,11 +117,15 @@ namespace Ryujinx audioOut.Dispose(); Logger.Shutdown(); + + DiscordClient.Dispose(); } private static void CurrentDomain_ProcessExit(object sender, EventArgs e) { Logger.Shutdown(); + + DiscordClient.Dispose(); } private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) @@ -133,26 +137,25 @@ namespace Ryujinx if (e.IsTerminating) { Logger.Shutdown(); + + DiscordClient.Dispose(); } } private static void SetGamePresence(Switch device) { - if (File.Exists("./discord-rpc.dll") || File.Exists("./discord-rpc.so")) + if (File.ReadAllLines("./RPsupported.dat").Contains(device.System.TitleID)) { - string[] RPsupported = File.ReadAllLines("./RPsupported"); - if (RPsupported.Contains(device.System.TitleID)) - { - Presence.largeImageKey = device.System.TitleID; - Presence.largeImageText = device.System.TitleName; - } - Presence.details = $"Playing {device.System.TitleName}"; - Presence.state = device.System.TitleID.ToUpper(); - Presence.smallImageKey = "ryujinx"; - Presence.smallImageText = "Ryujinx"; - Presence.startTimestamp = DateTimeOffset.Now.ToUnixTimeSeconds(); - DiscordRpc.UpdatePresence(Presence); + DiscordPresence.Assets.LargeImageKey = device.System.TitleID; + DiscordPresence.Assets.LargeImageText = device.System.TitleName; } + DiscordPresence.Details = $"Playing {device.System.TitleName}"; + DiscordPresence.State = device.System.TitleID.ToUpper(); + DiscordPresence.Assets.SmallImageKey = "ryujinx"; + DiscordPresence.Assets.SmallImageText = "Ryujinx"; + DiscordPresence.Timestamps = new DiscordRPC.Timestamps(DateTime.UtcNow); + + DiscordClient.SetPresence(DiscordPresence); } /// diff --git a/Ryujinx/RPsupported b/Ryujinx/RPsupported.dat similarity index 100% rename from Ryujinx/RPsupported rename to Ryujinx/RPsupported.dat diff --git a/Ryujinx/Ryujinx.csproj b/Ryujinx/Ryujinx.csproj index 51e38b2d1e..39aca350ac 100644 --- a/Ryujinx/Ryujinx.csproj +++ b/Ryujinx/Ryujinx.csproj @@ -8,6 +8,7 @@ + @@ -23,7 +24,7 @@ PreserveNewest - + PreserveNewest