From 72a0daf4864cfae5a97b25f01c11b4ceeac0e40b Mon Sep 17 00:00:00 2001 From: BuyMyMojo Date: Tue, 28 Feb 2023 02:50:32 +1100 Subject: [PATCH] Add Editor Rick Presence package --- .erp | 11 + Assets/ERP.meta | 8 + Assets/ERP/Documentation.meta | 8 + .../Editor Rich Presence Documentation.pdf | Bin 0 -> 95630 bytes ...ditor Rich Presence Documentation.pdf.meta | 7 + Assets/ERP/Editor.meta | 8 + Assets/ERP/Editor/ERP.cs | 203 + Assets/ERP/Editor/ERP.cs.meta | 11 + Assets/ERP/Editor/ERPSettings.cs | 77 + Assets/ERP/Editor/ERPSettings.cs.meta | 11 + Assets/ERP/Editor/ERPWindow.cs | 93 + Assets/ERP/Editor/ERPWindow.cs.meta | 11 + Assets/ERP/Editor/Plugins.meta | 8 + Assets/ERP/Editor/Plugins/DiscordSDK.meta | 8 + .../Plugins/DiscordSDK/ActivityManager.cs | 12 + .../DiscordSDK/ActivityManager.cs.meta | 11 + .../Editor/Plugins/DiscordSDK/Constants.cs | 9 + .../Plugins/DiscordSDK/Constants.cs.meta | 11 + Assets/ERP/Editor/Plugins/DiscordSDK/Core.cs | 4199 +++++++++++++++++ .../Editor/Plugins/DiscordSDK/Core.cs.meta | 11 + .../Editor/Plugins/DiscordSDK/ImageManager.cs | 53 + .../Plugins/DiscordSDK/ImageManager.cs.meta | 11 + .../Editor/Plugins/DiscordSDK/LobbyManager.cs | 26 + .../Plugins/DiscordSDK/LobbyManager.cs.meta | 11 + .../Plugins/DiscordSDK/StorageManager.cs | 20 + .../Plugins/DiscordSDK/StorageManager.cs.meta | 11 + .../Editor/Plugins/DiscordSDK/StoreManager.cs | 32 + .../Plugins/DiscordSDK/StoreManager.cs.meta | 11 + Assets/ERP/Editor/Plugins/DiscordSDK/x86.meta | 8 + .../DiscordSDK/x86/discord_game_sdk.dll | 3 + .../DiscordSDK/x86/discord_game_sdk.dll.meta | 80 + .../ERP/Editor/Plugins/DiscordSDK/x86_64.meta | 8 + .../DiscordSDK/x86_64/discord_game_sdk.dll | 3 + .../x86_64/discord_game_sdk.dll.meta | 80 + Assets/ERP/Editor/com.ben-w.erp.asmdef | 13 + Assets/ERP/Editor/com.ben-w.erp.asmdef.meta | 7 + Assets/ERP/README.md | 16 + Assets/ERP/README.md.meta | 7 + Assets/ERP/package.json | 17 + Assets/ERP/package.json.meta | 7 + 40 files changed, 5141 insertions(+) create mode 100644 .erp create mode 100644 Assets/ERP.meta create mode 100644 Assets/ERP/Documentation.meta create mode 100644 Assets/ERP/Documentation/Editor Rich Presence Documentation.pdf create mode 100644 Assets/ERP/Documentation/Editor Rich Presence Documentation.pdf.meta create mode 100644 Assets/ERP/Editor.meta create mode 100644 Assets/ERP/Editor/ERP.cs create mode 100644 Assets/ERP/Editor/ERP.cs.meta create mode 100644 Assets/ERP/Editor/ERPSettings.cs create mode 100644 Assets/ERP/Editor/ERPSettings.cs.meta create mode 100644 Assets/ERP/Editor/ERPWindow.cs create mode 100644 Assets/ERP/Editor/ERPWindow.cs.meta create mode 100644 Assets/ERP/Editor/Plugins.meta create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK.meta create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/ActivityManager.cs create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/ActivityManager.cs.meta create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/Constants.cs create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/Constants.cs.meta create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/Core.cs create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/Core.cs.meta create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/ImageManager.cs create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/ImageManager.cs.meta create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/LobbyManager.cs create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/LobbyManager.cs.meta create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/StorageManager.cs create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/StorageManager.cs.meta create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/StoreManager.cs create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/StoreManager.cs.meta create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/x86.meta create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/x86/discord_game_sdk.dll create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/x86/discord_game_sdk.dll.meta create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/x86_64.meta create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/x86_64/discord_game_sdk.dll create mode 100644 Assets/ERP/Editor/Plugins/DiscordSDK/x86_64/discord_game_sdk.dll.meta create mode 100644 Assets/ERP/Editor/com.ben-w.erp.asmdef create mode 100644 Assets/ERP/Editor/com.ben-w.erp.asmdef.meta create mode 100644 Assets/ERP/README.md create mode 100644 Assets/ERP/README.md.meta create mode 100644 Assets/ERP/package.json create mode 100644 Assets/ERP/package.json.meta diff --git a/.erp b/.erp new file mode 100644 index 0000000..b1c5956 --- /dev/null +++ b/.erp @@ -0,0 +1,11 @@ + + + true + true + false + false + true + 1677515252 + 522683637854076046 + false + \ No newline at end of file diff --git a/Assets/ERP.meta b/Assets/ERP.meta new file mode 100644 index 0000000..2093bc6 --- /dev/null +++ b/Assets/ERP.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 9dee676ed2a98d2439bd27dacba38c36 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Documentation.meta b/Assets/ERP/Documentation.meta new file mode 100644 index 0000000..7ad7810 --- /dev/null +++ b/Assets/ERP/Documentation.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 404dfd50bd7825149b4dc8d5c79ac837 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Documentation/Editor Rich Presence Documentation.pdf b/Assets/ERP/Documentation/Editor Rich Presence Documentation.pdf new file mode 100644 index 0000000000000000000000000000000000000000..6a99036996863e3c5ae8d88372974017f8108cb2 GIT binary patch literal 95630 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 KB^8zyLHb|Bs{XJ5 literal 0 HcmV?d00001 diff --git a/Assets/ERP/Documentation/Editor Rich Presence Documentation.pdf.meta b/Assets/ERP/Documentation/Editor Rich Presence Documentation.pdf.meta new file mode 100644 index 0000000..ba29d45 --- /dev/null +++ b/Assets/ERP/Documentation/Editor Rich Presence Documentation.pdf.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5126d240b3c42a449843d9abbc8fa0a8 +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Editor.meta b/Assets/ERP/Editor.meta new file mode 100644 index 0000000..0e5b686 --- /dev/null +++ b/Assets/ERP/Editor.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: dc28a777929b11d4db19be0bbf17326c +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Editor/ERP.cs b/Assets/ERP/Editor/ERP.cs new file mode 100644 index 0000000..f9bc556 --- /dev/null +++ b/Assets/ERP/Editor/ERP.cs @@ -0,0 +1,203 @@ +#if UNITY_EDITOR +using System; +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor.SceneManagement; +using UnityEditor; +using System.IO; +using System.Threading.Tasks; +using System.Threading; +using ERP.Discord; +using System.Diagnostics; +using Debug = UnityEngine.Debug; + +namespace ERP +{ + [InitializeOnLoad] + public static class ERP + { + private const string applicationId = "509465267630374935"; + private const string prefix = "ERP"; + + public static Discord.Discord discord { get; private set; } + + + public static string projectName { get; private set; } + public static string sceneName { get; private set; } + public static bool showSceneName = true; + public static bool showProjectName = true; + public static bool resetOnSceneChange = false; + public static bool debugMode = false; + public static bool EditorClosed = true; + public static long lastTimestamp = 0; + public static long lastSessionID = 0; + public static bool Errored = false; + + public static bool Failed; + static ERP() + { + ERPSettings.GetSettings(); + DelayStart(); + } + public static async void DelayStart(int delay = 1000) + { + await Task.Delay(delay); + Init(); + } + public static void Init() + { + if (Errored && lastSessionID == EditorAnalyticsSessionInfo.id) + { + if (debugMode) + LogWarning($"Error but in same session"); + return; + } + + if (!DiscordRunning()) + { + LogWarning("Can't find Discord's Process"); + Failed = true; + Errored = true; + ERPSettings.SaveSettings(); + return; + } + + try + { + discord = new Discord.Discord(long.Parse(applicationId), (long)CreateFlags.Default); + } + catch (Exception e) + { + if (debugMode) + LogWarning("Expected Error, retrying\n" + e.ToString()); + if (!Failed) + DelayStart(2000); + Failed = true; + return; + } + + if (!resetOnSceneChange || EditorAnalyticsSessionInfo.id != lastSessionID) + { + lastTimestamp = GetTimestamp(); + ERPSettings.SaveSettings(); + } + + lastSessionID = EditorAnalyticsSessionInfo.id; + + projectName = Application.productName; + sceneName = EditorSceneManager.GetActiveScene().name; + UpdateActivity(); + + EditorApplication.update += Update; + EditorSceneManager.sceneOpened += SceneOpened; + Log("Started!"); + } + + private static void SceneOpened(UnityEngine.SceneManagement.Scene scene, OpenSceneMode mode) + { + if (resetOnSceneChange) + lastTimestamp = GetTimestamp(); + sceneName = EditorSceneManager.GetActiveScene().name; + UpdateActivity(); + } + + private static void Update() + { + if (discord != null) + discord.RunCallbacks(); + + } + public static void UpdateActivity() + { + Log("Updating Activity"); + if (discord == null) + Init(); + + projectName = Application.productName; + sceneName = EditorSceneManager.GetActiveScene().name; + + var activityManager = discord.GetActivityManager(); + + Activity activity = new Activity + { + State = showProjectName ? projectName : "", + Details = showSceneName ? sceneName : "", + Timestamps = + { + Start = lastTimestamp + }, + Assets = + { + LargeImage = "logo", + LargeText = "Unity " + Application.unityVersion, + SmallImage = "marshmello", + SmallText = "ERP on Unity Asset Store", + }, + }; + + activityManager.UpdateActivity(activity, result => + { + if (result != Result.Ok) + LogError("Error from discord (" + result.ToString() + ")"); + else + Log("Discord Result = " + result.ToString()); + }); + + ERPSettings.SaveSettings(); + } + public static long GetTimestamp() + { + if (!resetOnSceneChange) + { + TimeSpan timeSpan = TimeSpan.FromMilliseconds(EditorAnalyticsSessionInfo.elapsedTime); + long timestamp = DateTimeOffset.Now.Add(timeSpan).ToUnixTimeSeconds(); + Log("Got time stamp: " + timestamp); + return timestamp; + } + long unixTimestamp = DateTimeOffset.Now.ToUnixTimeSeconds(); + Log("Got time stamp: " + unixTimestamp); + return unixTimestamp; + } + public static void Log(object message) + { + if (debugMode) + Debug.Log(prefix + ": " + message); + } + public static void LogWarning(object message) + { + if (debugMode) + Debug.LogWarning(prefix + ": " + message); + } + public static void LogError(object message) + { + Debug.LogError(prefix + ": " + message); + } + + private static bool DiscordRunning() + { + Process[] processes = Process.GetProcessesByName("Discord"); + + if (processes.Length == 0) + { + processes = Process.GetProcessesByName("DiscordPTB"); + + if (processes.Length == 0) + { + processes = Process.GetProcessesByName("DiscordCanary"); + } + } + + if (debugMode) + { + for (int i = 0; i < processes.Length; i++) + { + Log($"({i}/{processes.Length - 1})Found Process {processes[i].ProcessName}"); + } + } + return processes.Length != 0; + } + + } +} +#endif \ No newline at end of file diff --git a/Assets/ERP/Editor/ERP.cs.meta b/Assets/ERP/Editor/ERP.cs.meta new file mode 100644 index 0000000..f7c1720 --- /dev/null +++ b/Assets/ERP/Editor/ERP.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 22bb83fad6b4e1e44afed775331903a8 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Editor/ERPSettings.cs b/Assets/ERP/Editor/ERPSettings.cs new file mode 100644 index 0000000..6571ad2 --- /dev/null +++ b/Assets/ERP/Editor/ERPSettings.cs @@ -0,0 +1,77 @@ +#if UNITY_EDITOR +using System; +using System.IO; +using System.Collections; +using System.Collections.Generic; +using System.Xml; +using System.Xml.Serialization; +using UnityEngine; + +namespace ERP +{ + [Serializable] + public class ERPSettings + { + private static string path = Directory.GetCurrentDirectory() + "/.erp"; + public bool showSceneName; + public bool showProjectName; + public bool resetOnSceneChange; + public bool debugMode; + public bool EditorClosed; + public long LastTimestamp; + public long LastSessionID; + public bool Errored; + + public ERPSettings() { } + + public ERPSettings(bool showSceneName, bool showProjectName, bool resetOnSceneChange, bool debugMode, bool editorClosed, long lastTimestamp, long lastSessionID, bool errored) + { + this.showSceneName = showSceneName; + this.showProjectName = showProjectName; + this.resetOnSceneChange = resetOnSceneChange; + this.debugMode = debugMode; + EditorClosed = editorClosed; + LastTimestamp = lastTimestamp; + LastSessionID = lastSessionID; + Errored = errored; + } + + public static void GetSettings() + { + if (File.Exists(path)) + { + XmlSerializer serializer = new XmlSerializer(typeof(ERPSettings)); + FileStream stream = new FileStream(path, FileMode.Open); + ERPSettings settings = serializer.Deserialize(stream) as ERPSettings; + ApplySettings(settings); + stream.Close(); + } + } + + private static void ApplySettings(ERPSettings settings) + { + ERP.showSceneName = settings.showSceneName; + ERP.showProjectName = settings.showProjectName; + ERP.resetOnSceneChange = settings.resetOnSceneChange; + ERP.debugMode = settings.debugMode; + ERP.EditorClosed = settings.EditorClosed; + ERP.lastTimestamp = settings.LastTimestamp; + ERP.lastSessionID = settings.LastSessionID; + ERP.Errored = settings.Errored; + ERP.Log("Applied Settings from file"); + } + + public static void SaveSettings() + { + ERPSettings settings = new ERPSettings(ERP.showSceneName, ERP.showProjectName, ERP.resetOnSceneChange, ERP.debugMode, ERP.EditorClosed, ERP.lastTimestamp, ERP.lastSessionID, ERP.Errored); + + XmlSerializer serializer = new XmlSerializer(typeof(ERPSettings)); + var stream = new FileStream(path, FileMode.Create); + serializer.Serialize(stream, settings); + stream.Close(); + ERP.Log("Saved Settings"); + } + } + +} +#endif \ No newline at end of file diff --git a/Assets/ERP/Editor/ERPSettings.cs.meta b/Assets/ERP/Editor/ERPSettings.cs.meta new file mode 100644 index 0000000..ac2c8bb --- /dev/null +++ b/Assets/ERP/Editor/ERPSettings.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f2d151e101b964240b0e57a8cf391c3c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Editor/ERPWindow.cs b/Assets/ERP/Editor/ERPWindow.cs new file mode 100644 index 0000000..67e5658 --- /dev/null +++ b/Assets/ERP/Editor/ERPWindow.cs @@ -0,0 +1,93 @@ +#if UNITY_EDITOR +using System.Collections; +using System.Collections.Generic; +using UnityEngine; +using UnityEditor; + +namespace ERP +{ + public class ERPWindow : EditorWindow + { + private static ERPWindow _window; + + [MenuItem("Window/Editor Rich Presence")] + private static void Init() + { + _window = (ERPWindow)GetWindow(typeof(ERPWindow), false, "Editor Rich Presence"); + _window.Show(); + } + private void OnGUI() + { + if (ERP.discord == null && !ERP.Failed) + ERP.DelayStart(); + + if (ERP.Failed | ERP.Errored) + { + GUILayout.Label($"ERP Failed to start", EditorStyles.boldLabel); + if (GUILayout.Button("Retry")) + { + ERP.Errored = false; + ERP.Failed = false; + ERP.Init(); + } + return; + } + GUILayout.Label("Editor Rich Presence", EditorStyles.boldLabel); + + GUILayout.Label("Current Project: " + ERP.projectName); + GUILayout.Label("Current Scene: " + ERP.sceneName); + GUILayout.Label(string.Empty); + GUILayout.Label($"Scene Name Visible: {ERP.showSceneName}"); + GUILayout.Label($"Project Name Visible: {ERP.showProjectName}"); + GUILayout.Label($"Reset Timestap on scene change: {ERP.resetOnSceneChange}"); + + if (ToggleButton("Hide Scene name", "Show Scene name", ref ERP.showSceneName)) + { + ERP.UpdateActivity(); + ERPSettings.SaveSettings(); + } + if (ToggleButton("Hide Project name", "Show Project name", ref ERP.showProjectName)) + { + ERP.UpdateActivity(); + ERPSettings.SaveSettings(); + } + if (ToggleButton("Don't reset timestap on scene change", "Reset timestap on scene change", ref ERP.resetOnSceneChange)) + { + ERP.UpdateActivity(); + ERPSettings.SaveSettings(); + } + if (ToggleButton("Disable Debug Mode", "Enable Debug Mode", ref ERP.debugMode)) + { + ERPSettings.SaveSettings(); + } + GUILayout.Label(string.Empty); + GUILayout.BeginHorizontal(); + if (GUILayout.Button("GitHub Repository")) + { + Application.OpenURL("https://github.com/MarshMello0/Editor-Rich-Presence"); + } + if (GUILayout.Button("Asset Store Page")) + { + Application.OpenURL("https://assetstore.unity.com/packages/tools/utilities/editor-rich-presence-178736"); + } + GUILayout.EndHorizontal(); + + } + + private bool ToggleButton(string trueText, string falseText, ref bool value) + { + if (value && GUILayout.Button(trueText)) + { + value = false; + return true; + } + else if (!value && GUILayout.Button(falseText)) + { + value = true; + return true; + } + return false; + } + } +} +#endif \ No newline at end of file diff --git a/Assets/ERP/Editor/ERPWindow.cs.meta b/Assets/ERP/Editor/ERPWindow.cs.meta new file mode 100644 index 0000000..1de9c84 --- /dev/null +++ b/Assets/ERP/Editor/ERPWindow.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 59dfeb4cf2bfe5d40bc44adef75bc71c +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Editor/Plugins.meta b/Assets/ERP/Editor/Plugins.meta new file mode 100644 index 0000000..cec2d9b --- /dev/null +++ b/Assets/ERP/Editor/Plugins.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: f2f9d30f2a57de249b316cd189be4165 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK.meta b/Assets/ERP/Editor/Plugins/DiscordSDK.meta new file mode 100644 index 0000000..bc4b1ef --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: ce6f73dd7415ecd4aaa685f854de777e +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/ActivityManager.cs b/Assets/ERP/Editor/Plugins/DiscordSDK/ActivityManager.cs new file mode 100644 index 0000000..75c29c6 --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/ActivityManager.cs @@ -0,0 +1,12 @@ +using System; + +namespace ERP.Discord +{ + public partial class ActivityManager + { + public void RegisterCommand() + { + RegisterCommand(null); + } + } +} diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/ActivityManager.cs.meta b/Assets/ERP/Editor/Plugins/DiscordSDK/ActivityManager.cs.meta new file mode 100644 index 0000000..4c9b257 --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/ActivityManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 1bbf7726d48d669488894791799286e0 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/Constants.cs b/Assets/ERP/Editor/Plugins/DiscordSDK/Constants.cs new file mode 100644 index 0000000..5e91769 --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/Constants.cs @@ -0,0 +1,9 @@ +using System; + +namespace ERP.Discord +{ + static class Constants + { + public const string DllName = "discord_game_sdk"; + } +} diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/Constants.cs.meta b/Assets/ERP/Editor/Plugins/DiscordSDK/Constants.cs.meta new file mode 100644 index 0000000..e1ce7e9 --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/Constants.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2b81933783bc3c2448c5d19141baea99 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/Core.cs b/Assets/ERP/Editor/Plugins/DiscordSDK/Core.cs new file mode 100644 index 0000000..2840599 --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/Core.cs @@ -0,0 +1,4199 @@ +using System; +using System.Runtime.InteropServices; +using System.Text; + +namespace ERP.Discord +{ + public enum Result + { + Ok = 0, + ServiceUnavailable = 1, + InvalidVersion = 2, + LockFailed = 3, + InternalError = 4, + InvalidPayload = 5, + InvalidCommand = 6, + InvalidPermissions = 7, + NotFetched = 8, + NotFound = 9, + Conflict = 10, + InvalidSecret = 11, + InvalidJoinSecret = 12, + NoEligibleActivity = 13, + InvalidInvite = 14, + NotAuthenticated = 15, + InvalidAccessToken = 16, + ApplicationMismatch = 17, + InvalidDataUrl = 18, + InvalidBase64 = 19, + NotFiltered = 20, + LobbyFull = 21, + InvalidLobbySecret = 22, + InvalidFilename = 23, + InvalidFileSize = 24, + InvalidEntitlement = 25, + NotInstalled = 26, + NotRunning = 27, + InsufficientBuffer = 28, + PurchaseCanceled = 29, + InvalidGuild = 30, + InvalidEvent = 31, + InvalidChannel = 32, + InvalidOrigin = 33, + RateLimited = 34, + OAuth2Error = 35, + SelectChannelTimeout = 36, + GetGuildTimeout = 37, + SelectVoiceForceRequired = 38, + CaptureShortcutAlreadyListening = 39, + UnauthorizedForAchievement = 40, + InvalidGiftCode = 41, + PurchaseError = 42, + TransactionAborted = 43, + } + + public enum CreateFlags + { + Default = 0, + NoRequireDiscord = 1, + } + + public enum LogLevel + { + Error = 1, + Warn, + Info, + Debug, + } + + public enum UserFlag + { + Partner = 2, + HypeSquadEvents = 4, + HypeSquadHouse1 = 64, + HypeSquadHouse2 = 128, + HypeSquadHouse3 = 256, + } + + public enum PremiumType + { + None = 0, + Tier1 = 1, + Tier2 = 2, + } + + public enum ImageType + { + User, + } + + public enum ActivityType + { + Playing, + Streaming, + Listening, + Watching, + } + + public enum ActivityActionType + { + Join = 1, + Spectate, + } + + public enum ActivityJoinRequestReply + { + No, + Yes, + Ignore, + } + + public enum Status + { + Offline = 0, + Online = 1, + Idle = 2, + DoNotDisturb = 3, + } + + public enum RelationshipType + { + None, + Friend, + Blocked, + PendingIncoming, + PendingOutgoing, + Implicit, + } + + public enum LobbyType + { + Private = 1, + Public, + } + + public enum LobbySearchComparison + { + LessThanOrEqual = -2, + LessThan, + Equal, + GreaterThan, + GreaterThanOrEqual, + NotEqual, + } + + public enum LobbySearchCast + { + String = 1, + Number, + } + + public enum LobbySearchDistance + { + Local, + Default, + Extended, + Global, + } + + public enum EntitlementType + { + Purchase = 1, + PremiumSubscription, + DeveloperGift, + TestModePurchase, + FreePurchase, + UserGift, + PremiumPurchase, + } + + public enum SkuType + { + Application = 1, + DLC, + Consumable, + Bundle, + } + + public enum InputModeType + { + VoiceActivity = 0, + PushToTalk, + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct User + { + public Int64 Id; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string Username; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 8)] + public string Discriminator; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string Avatar; + + public bool Bot; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct OAuth2Token + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string AccessToken; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 1024)] + public string Scopes; + + public Int64 Expires; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct ImageHandle + { + public ImageType Type; + + public Int64 Id; + + public UInt32 Size; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct ImageDimensions + { + public UInt32 Width; + + public UInt32 Height; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct ActivityTimestamps + { + public Int64 Start; + + public Int64 End; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct ActivityAssets + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string LargeImage; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string LargeText; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string SmallImage; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string SmallText; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct PartySize + { + public Int32 CurrentSize; + + public Int32 MaxSize; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct ActivityParty + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string Id; + + public PartySize Size; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct ActivitySecrets + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string Match; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string Join; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string Spectate; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct Activity + { + public ActivityType Type; + + public Int64 ApplicationId; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string Name; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string State; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string Details; + + public ActivityTimestamps Timestamps; + + public ActivityAssets Assets; + + public ActivityParty Party; + + public ActivitySecrets Secrets; + + public bool Instance; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct Presence + { + public Status Status; + + public Activity Activity; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct Relationship + { + public RelationshipType Type; + + public User User; + + public Presence Presence; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct Lobby + { + public Int64 Id; + + public LobbyType Type; + + public Int64 OwnerId; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 128)] + public string Secret; + + public UInt32 Capacity; + + public bool Locked; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct FileStat + { + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 260)] + public string Filename; + + public UInt64 Size; + + public UInt64 LastModified; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct Entitlement + { + public Int64 Id; + + public EntitlementType Type; + + public Int64 SkuId; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct SkuPrice + { + public UInt32 Amount; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)] + public string Currency; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct Sku + { + public Int64 Id; + + public SkuType Type; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string Name; + + public SkuPrice Price; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct InputMode + { + public InputModeType Type; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 256)] + public string Shortcut; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct UserAchievement + { + public Int64 UserId; + + public Int64 AchievementId; + + public byte PercentComplete; + + [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 64)] + public string UnlockedAt; + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct LobbyTransaction + { + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIMethods + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result SetTypeMethod(IntPtr methodsPtr, LobbyType type); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result SetOwnerMethod(IntPtr methodsPtr, Int64 ownerId); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result SetCapacityMethod(IntPtr methodsPtr, UInt32 capacity); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result SetMetadataMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)]string key, [MarshalAs(UnmanagedType.LPStr)]string value); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result DeleteMetadataMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)]string key); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result SetLockedMethod(IntPtr methodsPtr, bool locked); + + internal SetTypeMethod SetType; + + internal SetOwnerMethod SetOwner; + + internal SetCapacityMethod SetCapacity; + + internal SetMetadataMethod SetMetadata; + + internal DeleteMetadataMethod DeleteMetadata; + + internal SetLockedMethod SetLocked; + } + + internal IntPtr MethodsPtr; + + internal Object MethodsStructure; + + private FFIMethods Methods + { + get + { + if (MethodsStructure == null) + { + MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods)); + } + return (FFIMethods)MethodsStructure; + } + + } + + public void SetType(LobbyType type) + { + if (MethodsPtr != IntPtr.Zero) + { + var res = Methods.SetType(MethodsPtr, type); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + } + + public void SetOwner(Int64 ownerId) + { + if (MethodsPtr != IntPtr.Zero) + { + var res = Methods.SetOwner(MethodsPtr, ownerId); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + } + + public void SetCapacity(UInt32 capacity) + { + if (MethodsPtr != IntPtr.Zero) + { + var res = Methods.SetCapacity(MethodsPtr, capacity); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + } + + public void SetMetadata(string key, string value) + { + if (MethodsPtr != IntPtr.Zero) + { + var res = Methods.SetMetadata(MethodsPtr, key, value); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + } + + public void DeleteMetadata(string key) + { + if (MethodsPtr != IntPtr.Zero) + { + var res = Methods.DeleteMetadata(MethodsPtr, key); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + } + + public void SetLocked(bool locked) + { + if (MethodsPtr != IntPtr.Zero) + { + var res = Methods.SetLocked(MethodsPtr, locked); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + } + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct LobbyMemberTransaction + { + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIMethods + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result SetMetadataMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)]string key, [MarshalAs(UnmanagedType.LPStr)]string value); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result DeleteMetadataMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)]string key); + + internal SetMetadataMethod SetMetadata; + + internal DeleteMetadataMethod DeleteMetadata; + } + + internal IntPtr MethodsPtr; + + internal Object MethodsStructure; + + private FFIMethods Methods + { + get + { + if (MethodsStructure == null) + { + MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods)); + } + return (FFIMethods)MethodsStructure; + } + + } + + public void SetMetadata(string key, string value) + { + if (MethodsPtr != IntPtr.Zero) + { + var res = Methods.SetMetadata(MethodsPtr, key, value); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + } + + public void DeleteMetadata(string key) + { + if (MethodsPtr != IntPtr.Zero) + { + var res = Methods.DeleteMetadata(MethodsPtr, key); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + } + } + + [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi)] + public partial struct LobbySearchQuery + { + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIMethods + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result FilterMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)]string key, LobbySearchComparison comparison, LobbySearchCast cast, [MarshalAs(UnmanagedType.LPStr)]string value); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result SortMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)]string key, LobbySearchCast cast, [MarshalAs(UnmanagedType.LPStr)]string value); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result LimitMethod(IntPtr methodsPtr, UInt32 limit); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result DistanceMethod(IntPtr methodsPtr, LobbySearchDistance distance); + + internal FilterMethod Filter; + + internal SortMethod Sort; + + internal LimitMethod Limit; + + internal DistanceMethod Distance; + } + + internal IntPtr MethodsPtr; + + internal Object MethodsStructure; + + private FFIMethods Methods + { + get + { + if (MethodsStructure == null) + { + MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods)); + } + return (FFIMethods)MethodsStructure; + } + + } + + public void Filter(string key, LobbySearchComparison comparison, LobbySearchCast cast, string value) + { + if (MethodsPtr != IntPtr.Zero) + { + var res = Methods.Filter(MethodsPtr, key, comparison, cast, value); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + } + + public void Sort(string key, LobbySearchCast cast, string value) + { + if (MethodsPtr != IntPtr.Zero) + { + var res = Methods.Sort(MethodsPtr, key, cast, value); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + } + + public void Limit(UInt32 limit) + { + if (MethodsPtr != IntPtr.Zero) + { + var res = Methods.Limit(MethodsPtr, limit); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + } + + public void Distance(LobbySearchDistance distance) + { + if (MethodsPtr != IntPtr.Zero) + { + var res = Methods.Distance(MethodsPtr, distance); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + } + } + + public partial class ResultException : Exception + { + public readonly Result Result; + + public ResultException(Result result) : base(result.ToString()) + { + } + } + + public partial class Discord : IDisposable + { + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIEvents + { + + } + + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIMethods + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void DestroyHandler(IntPtr MethodsPtr); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result RunCallbacksMethod(IntPtr methodsPtr); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SetLogHookCallback(IntPtr ptr, LogLevel level, [MarshalAs(UnmanagedType.LPStr)]string message); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SetLogHookMethod(IntPtr methodsPtr, LogLevel minLevel, IntPtr callbackData, SetLogHookCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate IntPtr GetApplicationManagerMethod(IntPtr discordPtr); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate IntPtr GetUserManagerMethod(IntPtr discordPtr); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate IntPtr GetImageManagerMethod(IntPtr discordPtr); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate IntPtr GetActivityManagerMethod(IntPtr discordPtr); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate IntPtr GetRelationshipManagerMethod(IntPtr discordPtr); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate IntPtr GetLobbyManagerMethod(IntPtr discordPtr); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate IntPtr GetNetworkManagerMethod(IntPtr discordPtr); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate IntPtr GetOverlayManagerMethod(IntPtr discordPtr); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate IntPtr GetStorageManagerMethod(IntPtr discordPtr); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate IntPtr GetStoreManagerMethod(IntPtr discordPtr); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate IntPtr GetVoiceManagerMethod(IntPtr discordPtr); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate IntPtr GetAchievementManagerMethod(IntPtr discordPtr); + + internal DestroyHandler Destroy; + + internal RunCallbacksMethod RunCallbacks; + + internal SetLogHookMethod SetLogHook; + + internal GetApplicationManagerMethod GetApplicationManager; + + internal GetUserManagerMethod GetUserManager; + + internal GetImageManagerMethod GetImageManager; + + internal GetActivityManagerMethod GetActivityManager; + + internal GetRelationshipManagerMethod GetRelationshipManager; + + internal GetLobbyManagerMethod GetLobbyManager; + + internal GetNetworkManagerMethod GetNetworkManager; + + internal GetOverlayManagerMethod GetOverlayManager; + + internal GetStorageManagerMethod GetStorageManager; + + internal GetStoreManagerMethod GetStoreManager; + + internal GetVoiceManagerMethod GetVoiceManager; + + internal GetAchievementManagerMethod GetAchievementManager; + } + + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFICreateParams + { + internal Int64 ClientId; + + internal UInt64 Flags; + + internal IntPtr Events; + + internal IntPtr EventData; + + internal IntPtr ApplicationEvents; + + internal UInt32 ApplicationVersion; + + internal IntPtr UserEvents; + + internal UInt32 UserVersion; + + internal IntPtr ImageEvents; + + internal UInt32 ImageVersion; + + internal IntPtr ActivityEvents; + + internal UInt32 ActivityVersion; + + internal IntPtr RelationshipEvents; + + internal UInt32 RelationshipVersion; + + internal IntPtr LobbyEvents; + + internal UInt32 LobbyVersion; + + internal IntPtr NetworkEvents; + + internal UInt32 NetworkVersion; + + internal IntPtr OverlayEvents; + + internal UInt32 OverlayVersion; + + internal IntPtr StorageEvents; + + internal UInt32 StorageVersion; + + internal IntPtr StoreEvents; + + internal UInt32 StoreVersion; + + internal IntPtr VoiceEvents; + + internal UInt32 VoiceVersion; + + internal IntPtr AchievementEvents; + + internal UInt32 AchievementVersion; + } + + [DllImport(Constants.DllName, ExactSpelling = true, CallingConvention = CallingConvention.Cdecl)] + private static extern Result DiscordCreate(UInt32 version, ref FFICreateParams createParams, out IntPtr manager); + + public delegate void SetLogHookHandler(LogLevel level, string message); + + private GCHandle SelfHandle; + + private IntPtr EventsPtr; + + private FFIEvents Events; + + private IntPtr ApplicationEventsPtr; + + private ApplicationManager.FFIEvents ApplicationEvents; + + internal ApplicationManager ApplicationManagerInstance; + + private IntPtr UserEventsPtr; + + private UserManager.FFIEvents UserEvents; + + internal UserManager UserManagerInstance; + + private IntPtr ImageEventsPtr; + + private ImageManager.FFIEvents ImageEvents; + + internal ImageManager ImageManagerInstance; + + private IntPtr ActivityEventsPtr; + + private ActivityManager.FFIEvents ActivityEvents; + + internal ActivityManager ActivityManagerInstance; + + private IntPtr RelationshipEventsPtr; + + private RelationshipManager.FFIEvents RelationshipEvents; + + internal RelationshipManager RelationshipManagerInstance; + + private IntPtr LobbyEventsPtr; + + private LobbyManager.FFIEvents LobbyEvents; + + internal LobbyManager LobbyManagerInstance; + + private IntPtr NetworkEventsPtr; + + private NetworkManager.FFIEvents NetworkEvents; + + internal NetworkManager NetworkManagerInstance; + + private IntPtr OverlayEventsPtr; + + private OverlayManager.FFIEvents OverlayEvents; + + internal OverlayManager OverlayManagerInstance; + + private IntPtr StorageEventsPtr; + + private StorageManager.FFIEvents StorageEvents; + + internal StorageManager StorageManagerInstance; + + private IntPtr StoreEventsPtr; + + private StoreManager.FFIEvents StoreEvents; + + internal StoreManager StoreManagerInstance; + + private IntPtr VoiceEventsPtr; + + private VoiceManager.FFIEvents VoiceEvents; + + internal VoiceManager VoiceManagerInstance; + + private IntPtr AchievementEventsPtr; + + private AchievementManager.FFIEvents AchievementEvents; + + internal AchievementManager AchievementManagerInstance; + + private IntPtr MethodsPtr; + + private Object MethodsStructure; + + private FFIMethods Methods + { + get + { + if (MethodsStructure == null) + { + MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods)); + } + return (FFIMethods)MethodsStructure; + } + + } + + private GCHandle? setLogHook; + + public Discord(Int64 clientId, UInt64 flags) + { + FFICreateParams createParams; + createParams.ClientId = clientId; + createParams.Flags = flags; + Events = new FFIEvents(); + EventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(Events)); + createParams.Events = EventsPtr; + SelfHandle = GCHandle.Alloc(this); + createParams.EventData = GCHandle.ToIntPtr(SelfHandle); + ApplicationEvents = new ApplicationManager.FFIEvents(); + ApplicationEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(ApplicationEvents)); + createParams.ApplicationEvents = ApplicationEventsPtr; + createParams.ApplicationVersion = 1; + UserEvents = new UserManager.FFIEvents(); + UserEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(UserEvents)); + createParams.UserEvents = UserEventsPtr; + createParams.UserVersion = 1; + ImageEvents = new ImageManager.FFIEvents(); + ImageEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(ImageEvents)); + createParams.ImageEvents = ImageEventsPtr; + createParams.ImageVersion = 1; + ActivityEvents = new ActivityManager.FFIEvents(); + ActivityEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(ActivityEvents)); + createParams.ActivityEvents = ActivityEventsPtr; + createParams.ActivityVersion = 1; + RelationshipEvents = new RelationshipManager.FFIEvents(); + RelationshipEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(RelationshipEvents)); + createParams.RelationshipEvents = RelationshipEventsPtr; + createParams.RelationshipVersion = 1; + LobbyEvents = new LobbyManager.FFIEvents(); + LobbyEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(LobbyEvents)); + createParams.LobbyEvents = LobbyEventsPtr; + createParams.LobbyVersion = 1; + NetworkEvents = new NetworkManager.FFIEvents(); + NetworkEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(NetworkEvents)); + createParams.NetworkEvents = NetworkEventsPtr; + createParams.NetworkVersion = 1; + OverlayEvents = new OverlayManager.FFIEvents(); + OverlayEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(OverlayEvents)); + createParams.OverlayEvents = OverlayEventsPtr; + createParams.OverlayVersion = 1; + StorageEvents = new StorageManager.FFIEvents(); + StorageEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(StorageEvents)); + createParams.StorageEvents = StorageEventsPtr; + createParams.StorageVersion = 1; + StoreEvents = new StoreManager.FFIEvents(); + StoreEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(StoreEvents)); + createParams.StoreEvents = StoreEventsPtr; + createParams.StoreVersion = 1; + VoiceEvents = new VoiceManager.FFIEvents(); + VoiceEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(VoiceEvents)); + createParams.VoiceEvents = VoiceEventsPtr; + createParams.VoiceVersion = 1; + AchievementEvents = new AchievementManager.FFIEvents(); + AchievementEventsPtr = Marshal.AllocHGlobal(Marshal.SizeOf(AchievementEvents)); + createParams.AchievementEvents = AchievementEventsPtr; + createParams.AchievementVersion = 1; + InitEvents(EventsPtr, ref Events); + var result = DiscordCreate(2, ref createParams, out MethodsPtr); + if (result != Result.Ok) + { + Dispose(); + throw new ResultException(result); + } + } + + private void InitEvents(IntPtr eventsPtr, ref FFIEvents events) + { + Marshal.StructureToPtr(events, eventsPtr, false); + } + + public void Dispose() + { + if (MethodsPtr != IntPtr.Zero) + { + Methods.Destroy(MethodsPtr); + } + SelfHandle.Free(); + Marshal.FreeHGlobal(EventsPtr); + Marshal.FreeHGlobal(ApplicationEventsPtr); + Marshal.FreeHGlobal(UserEventsPtr); + Marshal.FreeHGlobal(ImageEventsPtr); + Marshal.FreeHGlobal(ActivityEventsPtr); + Marshal.FreeHGlobal(RelationshipEventsPtr); + Marshal.FreeHGlobal(LobbyEventsPtr); + Marshal.FreeHGlobal(NetworkEventsPtr); + Marshal.FreeHGlobal(OverlayEventsPtr); + Marshal.FreeHGlobal(StorageEventsPtr); + Marshal.FreeHGlobal(StoreEventsPtr); + Marshal.FreeHGlobal(VoiceEventsPtr); + Marshal.FreeHGlobal(AchievementEventsPtr); + if (setLogHook.HasValue) { + setLogHook.Value.Free(); + } + } + + public void RunCallbacks() + { + var res = Methods.RunCallbacks(MethodsPtr); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + [MonoPInvokeCallback] + private static void SetLogHookCallbackImpl(IntPtr ptr, LogLevel level, string message) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + SetLogHookHandler callback = (SetLogHookHandler)h.Target; + callback(level, message); + } + + public void SetLogHook(LogLevel minLevel, SetLogHookHandler callback) + { + if (setLogHook.HasValue) { + setLogHook.Value.Free(); + } + setLogHook = GCHandle.Alloc(callback); + Methods.SetLogHook(MethodsPtr, minLevel, GCHandle.ToIntPtr(setLogHook.Value), SetLogHookCallbackImpl); + } + + public ApplicationManager GetApplicationManager() + { + if (ApplicationManagerInstance == null) { + ApplicationManagerInstance = new ApplicationManager( + Methods.GetApplicationManager(MethodsPtr), + ApplicationEventsPtr, + ref ApplicationEvents + ); + } + return ApplicationManagerInstance; + } + + public UserManager GetUserManager() + { + if (UserManagerInstance == null) { + UserManagerInstance = new UserManager( + Methods.GetUserManager(MethodsPtr), + UserEventsPtr, + ref UserEvents + ); + } + return UserManagerInstance; + } + + public ImageManager GetImageManager() + { + if (ImageManagerInstance == null) { + ImageManagerInstance = new ImageManager( + Methods.GetImageManager(MethodsPtr), + ImageEventsPtr, + ref ImageEvents + ); + } + return ImageManagerInstance; + } + + public ActivityManager GetActivityManager() + { + if (ActivityManagerInstance == null) { + ActivityManagerInstance = new ActivityManager( + Methods.GetActivityManager(MethodsPtr), + ActivityEventsPtr, + ref ActivityEvents + ); + } + return ActivityManagerInstance; + } + + public RelationshipManager GetRelationshipManager() + { + if (RelationshipManagerInstance == null) { + RelationshipManagerInstance = new RelationshipManager( + Methods.GetRelationshipManager(MethodsPtr), + RelationshipEventsPtr, + ref RelationshipEvents + ); + } + return RelationshipManagerInstance; + } + + public LobbyManager GetLobbyManager() + { + if (LobbyManagerInstance == null) { + LobbyManagerInstance = new LobbyManager( + Methods.GetLobbyManager(MethodsPtr), + LobbyEventsPtr, + ref LobbyEvents + ); + } + return LobbyManagerInstance; + } + + public NetworkManager GetNetworkManager() + { + if (NetworkManagerInstance == null) { + NetworkManagerInstance = new NetworkManager( + Methods.GetNetworkManager(MethodsPtr), + NetworkEventsPtr, + ref NetworkEvents + ); + } + return NetworkManagerInstance; + } + + public OverlayManager GetOverlayManager() + { + if (OverlayManagerInstance == null) { + OverlayManagerInstance = new OverlayManager( + Methods.GetOverlayManager(MethodsPtr), + OverlayEventsPtr, + ref OverlayEvents + ); + } + return OverlayManagerInstance; + } + + public StorageManager GetStorageManager() + { + if (StorageManagerInstance == null) { + StorageManagerInstance = new StorageManager( + Methods.GetStorageManager(MethodsPtr), + StorageEventsPtr, + ref StorageEvents + ); + } + return StorageManagerInstance; + } + + public StoreManager GetStoreManager() + { + if (StoreManagerInstance == null) { + StoreManagerInstance = new StoreManager( + Methods.GetStoreManager(MethodsPtr), + StoreEventsPtr, + ref StoreEvents + ); + } + return StoreManagerInstance; + } + + public VoiceManager GetVoiceManager() + { + if (VoiceManagerInstance == null) { + VoiceManagerInstance = new VoiceManager( + Methods.GetVoiceManager(MethodsPtr), + VoiceEventsPtr, + ref VoiceEvents + ); + } + return VoiceManagerInstance; + } + + public AchievementManager GetAchievementManager() + { + if (AchievementManagerInstance == null) { + AchievementManagerInstance = new AchievementManager( + Methods.GetAchievementManager(MethodsPtr), + AchievementEventsPtr, + ref AchievementEvents + ); + } + return AchievementManagerInstance; + } + } + + internal partial class MonoPInvokeCallbackAttribute : Attribute + { + + } + + public partial class ApplicationManager + { + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIEvents + { + + } + + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIMethods + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ValidateOrExitCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ValidateOrExitMethod(IntPtr methodsPtr, IntPtr callbackData, ValidateOrExitCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void GetCurrentLocaleMethod(IntPtr methodsPtr, StringBuilder locale); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void GetCurrentBranchMethod(IntPtr methodsPtr, StringBuilder branch); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void GetOAuth2TokenCallback(IntPtr ptr, Result result, ref OAuth2Token oauth2Token); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void GetOAuth2TokenMethod(IntPtr methodsPtr, IntPtr callbackData, GetOAuth2TokenCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void GetTicketCallback(IntPtr ptr, Result result, [MarshalAs(UnmanagedType.LPStr)]ref string data); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void GetTicketMethod(IntPtr methodsPtr, IntPtr callbackData, GetTicketCallback callback); + + internal ValidateOrExitMethod ValidateOrExit; + + internal GetCurrentLocaleMethod GetCurrentLocale; + + internal GetCurrentBranchMethod GetCurrentBranch; + + internal GetOAuth2TokenMethod GetOAuth2Token; + + internal GetTicketMethod GetTicket; + } + + public delegate void ValidateOrExitHandler(Result result); + + public delegate void GetOAuth2TokenHandler(Result result, ref OAuth2Token oauth2Token); + + public delegate void GetTicketHandler(Result result, ref string data); + + private IntPtr MethodsPtr; + + private Object MethodsStructure; + + private FFIMethods Methods + { + get + { + if (MethodsStructure == null) + { + MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods)); + } + return (FFIMethods)MethodsStructure; + } + + } + + internal ApplicationManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events) + { + if (eventsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + InitEvents(eventsPtr, ref events); + MethodsPtr = ptr; + if (MethodsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + } + + private void InitEvents(IntPtr eventsPtr, ref FFIEvents events) + { + Marshal.StructureToPtr(events, eventsPtr, false); + } + + [MonoPInvokeCallback] + private static void ValidateOrExitCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + ValidateOrExitHandler callback = (ValidateOrExitHandler)h.Target; + h.Free(); + callback(result); + } + + public void ValidateOrExit(ValidateOrExitHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.ValidateOrExit(MethodsPtr, GCHandle.ToIntPtr(wrapped), ValidateOrExitCallbackImpl); + } + + public string GetCurrentLocale() + { + var ret = new StringBuilder(128); + Methods.GetCurrentLocale(MethodsPtr, ret); + return ret.ToString(); + } + + public string GetCurrentBranch() + { + var ret = new StringBuilder(4096); + Methods.GetCurrentBranch(MethodsPtr, ret); + return ret.ToString(); + } + + [MonoPInvokeCallback] + private static void GetOAuth2TokenCallbackImpl(IntPtr ptr, Result result, ref OAuth2Token oauth2Token) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + GetOAuth2TokenHandler callback = (GetOAuth2TokenHandler)h.Target; + h.Free(); + callback(result, ref oauth2Token); + } + + public void GetOAuth2Token(GetOAuth2TokenHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.GetOAuth2Token(MethodsPtr, GCHandle.ToIntPtr(wrapped), GetOAuth2TokenCallbackImpl); + } + + [MonoPInvokeCallback] + private static void GetTicketCallbackImpl(IntPtr ptr, Result result, ref string data) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + GetTicketHandler callback = (GetTicketHandler)h.Target; + h.Free(); + callback(result, ref data); + } + + public void GetTicket(GetTicketHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.GetTicket(MethodsPtr, GCHandle.ToIntPtr(wrapped), GetTicketCallbackImpl); + } + } + + public partial class UserManager + { + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIEvents + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CurrentUserUpdateHandler(IntPtr ptr); + + internal CurrentUserUpdateHandler OnCurrentUserUpdate; + } + + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIMethods + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetCurrentUserMethod(IntPtr methodsPtr, ref User currentUser); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void GetUserCallback(IntPtr ptr, Result result, ref User user); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void GetUserMethod(IntPtr methodsPtr, Int64 userId, IntPtr callbackData, GetUserCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetCurrentUserPremiumTypeMethod(IntPtr methodsPtr, ref PremiumType premiumType); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result CurrentUserHasFlagMethod(IntPtr methodsPtr, UserFlag flag, ref bool hasFlag); + + internal GetCurrentUserMethod GetCurrentUser; + + internal GetUserMethod GetUser; + + internal GetCurrentUserPremiumTypeMethod GetCurrentUserPremiumType; + + internal CurrentUserHasFlagMethod CurrentUserHasFlag; + } + + public delegate void GetUserHandler(Result result, ref User user); + + public delegate void CurrentUserUpdateHandler(); + + private IntPtr MethodsPtr; + + private Object MethodsStructure; + + private FFIMethods Methods + { + get + { + if (MethodsStructure == null) + { + MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods)); + } + return (FFIMethods)MethodsStructure; + } + + } + + public event CurrentUserUpdateHandler OnCurrentUserUpdate; + + internal UserManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events) + { + if (eventsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + InitEvents(eventsPtr, ref events); + MethodsPtr = ptr; + if (MethodsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + } + + private void InitEvents(IntPtr eventsPtr, ref FFIEvents events) + { + events.OnCurrentUserUpdate = OnCurrentUserUpdateImpl; + Marshal.StructureToPtr(events, eventsPtr, false); + } + + public User GetCurrentUser() + { + var ret = new User(); + var res = Methods.GetCurrentUser(MethodsPtr, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + [MonoPInvokeCallback] + private static void GetUserCallbackImpl(IntPtr ptr, Result result, ref User user) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + GetUserHandler callback = (GetUserHandler)h.Target; + h.Free(); + callback(result, ref user); + } + + public void GetUser(Int64 userId, GetUserHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.GetUser(MethodsPtr, userId, GCHandle.ToIntPtr(wrapped), GetUserCallbackImpl); + } + + public PremiumType GetCurrentUserPremiumType() + { + var ret = new PremiumType(); + var res = Methods.GetCurrentUserPremiumType(MethodsPtr, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public bool CurrentUserHasFlag(UserFlag flag) + { + var ret = new bool(); + var res = Methods.CurrentUserHasFlag(MethodsPtr, flag, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + [MonoPInvokeCallback] + private static void OnCurrentUserUpdateImpl(IntPtr ptr) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.UserManagerInstance.OnCurrentUserUpdate != null) + { + d.UserManagerInstance.OnCurrentUserUpdate.Invoke(); + } + } + } + + public partial class ImageManager + { + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIEvents + { + + } + + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIMethods + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void FetchCallback(IntPtr ptr, Result result, ImageHandle handleResult); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void FetchMethod(IntPtr methodsPtr, ImageHandle handle, bool refresh, IntPtr callbackData, FetchCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetDimensionsMethod(IntPtr methodsPtr, ImageHandle handle, ref ImageDimensions dimensions); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetDataMethod(IntPtr methodsPtr, ImageHandle handle, byte[] data, Int32 dataLen); + + internal FetchMethod Fetch; + + internal GetDimensionsMethod GetDimensions; + + internal GetDataMethod GetData; + } + + public delegate void FetchHandler(Result result, ImageHandle handleResult); + + private IntPtr MethodsPtr; + + private Object MethodsStructure; + + private FFIMethods Methods + { + get + { + if (MethodsStructure == null) + { + MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods)); + } + return (FFIMethods)MethodsStructure; + } + + } + + internal ImageManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events) + { + if (eventsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + InitEvents(eventsPtr, ref events); + MethodsPtr = ptr; + if (MethodsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + } + + private void InitEvents(IntPtr eventsPtr, ref FFIEvents events) + { + Marshal.StructureToPtr(events, eventsPtr, false); + } + + [MonoPInvokeCallback] + private static void FetchCallbackImpl(IntPtr ptr, Result result, ImageHandle handleResult) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + FetchHandler callback = (FetchHandler)h.Target; + h.Free(); + callback(result, handleResult); + } + + public void Fetch(ImageHandle handle, bool refresh, FetchHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.Fetch(MethodsPtr, handle, refresh, GCHandle.ToIntPtr(wrapped), FetchCallbackImpl); + } + + public ImageDimensions GetDimensions(ImageHandle handle) + { + var ret = new ImageDimensions(); + var res = Methods.GetDimensions(MethodsPtr, handle, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public void GetData(ImageHandle handle, byte[] data) + { + var res = Methods.GetData(MethodsPtr, handle, data, data.Length); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + } + + public partial class ActivityManager + { + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIEvents + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ActivityJoinHandler(IntPtr ptr, [MarshalAs(UnmanagedType.LPStr)]string secret); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ActivitySpectateHandler(IntPtr ptr, [MarshalAs(UnmanagedType.LPStr)]string secret); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ActivityJoinRequestHandler(IntPtr ptr, ref User user); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ActivityInviteHandler(IntPtr ptr, ActivityActionType type, ref User user, ref Activity activity); + + internal ActivityJoinHandler OnActivityJoin; + + internal ActivitySpectateHandler OnActivitySpectate; + + internal ActivityJoinRequestHandler OnActivityJoinRequest; + + internal ActivityInviteHandler OnActivityInvite; + } + + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIMethods + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result RegisterCommandMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)]string command); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result RegisterSteamMethod(IntPtr methodsPtr, UInt32 steamId); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void UpdateActivityCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void UpdateActivityMethod(IntPtr methodsPtr, ref Activity activity, IntPtr callbackData, UpdateActivityCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ClearActivityCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ClearActivityMethod(IntPtr methodsPtr, IntPtr callbackData, ClearActivityCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SendRequestReplyCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SendRequestReplyMethod(IntPtr methodsPtr, Int64 userId, ActivityJoinRequestReply reply, IntPtr callbackData, SendRequestReplyCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SendInviteCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SendInviteMethod(IntPtr methodsPtr, Int64 userId, ActivityActionType type, [MarshalAs(UnmanagedType.LPStr)]string content, IntPtr callbackData, SendInviteCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void AcceptInviteCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void AcceptInviteMethod(IntPtr methodsPtr, Int64 userId, IntPtr callbackData, AcceptInviteCallback callback); + + internal RegisterCommandMethod RegisterCommand; + + internal RegisterSteamMethod RegisterSteam; + + internal UpdateActivityMethod UpdateActivity; + + internal ClearActivityMethod ClearActivity; + + internal SendRequestReplyMethod SendRequestReply; + + internal SendInviteMethod SendInvite; + + internal AcceptInviteMethod AcceptInvite; + } + + public delegate void UpdateActivityHandler(Result result); + + public delegate void ClearActivityHandler(Result result); + + public delegate void SendRequestReplyHandler(Result result); + + public delegate void SendInviteHandler(Result result); + + public delegate void AcceptInviteHandler(Result result); + + public delegate void ActivityJoinHandler(string secret); + + public delegate void ActivitySpectateHandler(string secret); + + public delegate void ActivityJoinRequestHandler(ref User user); + + public delegate void ActivityInviteHandler(ActivityActionType type, ref User user, ref Activity activity); + + private IntPtr MethodsPtr; + + private Object MethodsStructure; + + private FFIMethods Methods + { + get + { + if (MethodsStructure == null) + { + MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods)); + } + return (FFIMethods)MethodsStructure; + } + + } + + public event ActivityJoinHandler OnActivityJoin; + + public event ActivitySpectateHandler OnActivitySpectate; + + public event ActivityJoinRequestHandler OnActivityJoinRequest; + + public event ActivityInviteHandler OnActivityInvite; + + internal ActivityManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events) + { + if (eventsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + InitEvents(eventsPtr, ref events); + MethodsPtr = ptr; + if (MethodsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + } + + private void InitEvents(IntPtr eventsPtr, ref FFIEvents events) + { + events.OnActivityJoin = OnActivityJoinImpl; + events.OnActivitySpectate = OnActivitySpectateImpl; + events.OnActivityJoinRequest = OnActivityJoinRequestImpl; + events.OnActivityInvite = OnActivityInviteImpl; + Marshal.StructureToPtr(events, eventsPtr, false); + } + + public void RegisterCommand(string command) + { + var res = Methods.RegisterCommand(MethodsPtr, command); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + public void RegisterSteam(UInt32 steamId) + { + var res = Methods.RegisterSteam(MethodsPtr, steamId); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + [MonoPInvokeCallback] + private static void UpdateActivityCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + UpdateActivityHandler callback = (UpdateActivityHandler)h.Target; + h.Free(); + callback(result); + } + + public void UpdateActivity(Activity activity, UpdateActivityHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.UpdateActivity(MethodsPtr, ref activity, GCHandle.ToIntPtr(wrapped), UpdateActivityCallbackImpl); + } + + [MonoPInvokeCallback] + private static void ClearActivityCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + ClearActivityHandler callback = (ClearActivityHandler)h.Target; + h.Free(); + callback(result); + } + + public void ClearActivity(ClearActivityHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.ClearActivity(MethodsPtr, GCHandle.ToIntPtr(wrapped), ClearActivityCallbackImpl); + } + + [MonoPInvokeCallback] + private static void SendRequestReplyCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + SendRequestReplyHandler callback = (SendRequestReplyHandler)h.Target; + h.Free(); + callback(result); + } + + public void SendRequestReply(Int64 userId, ActivityJoinRequestReply reply, SendRequestReplyHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.SendRequestReply(MethodsPtr, userId, reply, GCHandle.ToIntPtr(wrapped), SendRequestReplyCallbackImpl); + } + + [MonoPInvokeCallback] + private static void SendInviteCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + SendInviteHandler callback = (SendInviteHandler)h.Target; + h.Free(); + callback(result); + } + + public void SendInvite(Int64 userId, ActivityActionType type, string content, SendInviteHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.SendInvite(MethodsPtr, userId, type, content, GCHandle.ToIntPtr(wrapped), SendInviteCallbackImpl); + } + + [MonoPInvokeCallback] + private static void AcceptInviteCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + AcceptInviteHandler callback = (AcceptInviteHandler)h.Target; + h.Free(); + callback(result); + } + + public void AcceptInvite(Int64 userId, AcceptInviteHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.AcceptInvite(MethodsPtr, userId, GCHandle.ToIntPtr(wrapped), AcceptInviteCallbackImpl); + } + + [MonoPInvokeCallback] + private static void OnActivityJoinImpl(IntPtr ptr, string secret) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.ActivityManagerInstance.OnActivityJoin != null) + { + d.ActivityManagerInstance.OnActivityJoin.Invoke(secret); + } + } + + [MonoPInvokeCallback] + private static void OnActivitySpectateImpl(IntPtr ptr, string secret) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.ActivityManagerInstance.OnActivitySpectate != null) + { + d.ActivityManagerInstance.OnActivitySpectate.Invoke(secret); + } + } + + [MonoPInvokeCallback] + private static void OnActivityJoinRequestImpl(IntPtr ptr, ref User user) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.ActivityManagerInstance.OnActivityJoinRequest != null) + { + d.ActivityManagerInstance.OnActivityJoinRequest.Invoke(ref user); + } + } + + [MonoPInvokeCallback] + private static void OnActivityInviteImpl(IntPtr ptr, ActivityActionType type, ref User user, ref Activity activity) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.ActivityManagerInstance.OnActivityInvite != null) + { + d.ActivityManagerInstance.OnActivityInvite.Invoke(type, ref user, ref activity); + } + } + } + + public partial class RelationshipManager + { + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIEvents + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void RefreshHandler(IntPtr ptr); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void RelationshipUpdateHandler(IntPtr ptr, ref Relationship relationship); + + internal RefreshHandler OnRefresh; + + internal RelationshipUpdateHandler OnRelationshipUpdate; + } + + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIMethods + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate bool FilterCallback(IntPtr ptr, ref Relationship relationship); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void FilterMethod(IntPtr methodsPtr, IntPtr callbackData, FilterCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result CountMethod(IntPtr methodsPtr, ref Int32 count); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetMethod(IntPtr methodsPtr, Int64 userId, ref Relationship relationship); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetAtMethod(IntPtr methodsPtr, UInt32 index, ref Relationship relationship); + + internal FilterMethod Filter; + + internal CountMethod Count; + + internal GetMethod Get; + + internal GetAtMethod GetAt; + } + + public delegate bool FilterHandler(ref Relationship relationship); + + public delegate void RefreshHandler(); + + public delegate void RelationshipUpdateHandler(ref Relationship relationship); + + private IntPtr MethodsPtr; + + private Object MethodsStructure; + + private FFIMethods Methods + { + get + { + if (MethodsStructure == null) + { + MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods)); + } + return (FFIMethods)MethodsStructure; + } + + } + + public event RefreshHandler OnRefresh; + + public event RelationshipUpdateHandler OnRelationshipUpdate; + + internal RelationshipManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events) + { + if (eventsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + InitEvents(eventsPtr, ref events); + MethodsPtr = ptr; + if (MethodsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + } + + private void InitEvents(IntPtr eventsPtr, ref FFIEvents events) + { + events.OnRefresh = OnRefreshImpl; + events.OnRelationshipUpdate = OnRelationshipUpdateImpl; + Marshal.StructureToPtr(events, eventsPtr, false); + } + + [MonoPInvokeCallback] + private static bool FilterCallbackImpl(IntPtr ptr, ref Relationship relationship) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + FilterHandler callback = (FilterHandler)h.Target; + return callback(ref relationship); + } + + public void Filter(FilterHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.Filter(MethodsPtr, GCHandle.ToIntPtr(wrapped), FilterCallbackImpl); + wrapped.Free(); + } + + public Int32 Count() + { + var ret = new Int32(); + var res = Methods.Count(MethodsPtr, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public Relationship Get(Int64 userId) + { + var ret = new Relationship(); + var res = Methods.Get(MethodsPtr, userId, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public Relationship GetAt(UInt32 index) + { + var ret = new Relationship(); + var res = Methods.GetAt(MethodsPtr, index, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + [MonoPInvokeCallback] + private static void OnRefreshImpl(IntPtr ptr) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.RelationshipManagerInstance.OnRefresh != null) + { + d.RelationshipManagerInstance.OnRefresh.Invoke(); + } + } + + [MonoPInvokeCallback] + private static void OnRelationshipUpdateImpl(IntPtr ptr, ref Relationship relationship) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.RelationshipManagerInstance.OnRelationshipUpdate != null) + { + d.RelationshipManagerInstance.OnRelationshipUpdate.Invoke(ref relationship); + } + } + } + + public partial class LobbyManager + { + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIEvents + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void LobbyUpdateHandler(IntPtr ptr, Int64 lobbyId); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void LobbyDeleteHandler(IntPtr ptr, Int64 lobbyId, UInt32 reason); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void MemberConnectHandler(IntPtr ptr, Int64 lobbyId, Int64 userId); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void MemberUpdateHandler(IntPtr ptr, Int64 lobbyId, Int64 userId); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void MemberDisconnectHandler(IntPtr ptr, Int64 lobbyId, Int64 userId); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void LobbyMessageHandler(IntPtr ptr, Int64 lobbyId, Int64 userId, IntPtr dataPtr, Int32 dataLen); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SpeakingHandler(IntPtr ptr, Int64 lobbyId, Int64 userId, bool speaking); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void NetworkMessageHandler(IntPtr ptr, Int64 lobbyId, Int64 userId, byte channelId, IntPtr dataPtr, Int32 dataLen); + + internal LobbyUpdateHandler OnLobbyUpdate; + + internal LobbyDeleteHandler OnLobbyDelete; + + internal MemberConnectHandler OnMemberConnect; + + internal MemberUpdateHandler OnMemberUpdate; + + internal MemberDisconnectHandler OnMemberDisconnect; + + internal LobbyMessageHandler OnLobbyMessage; + + internal SpeakingHandler OnSpeaking; + + internal NetworkMessageHandler OnNetworkMessage; + } + + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIMethods + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetLobbyCreateTransactionMethod(IntPtr methodsPtr, ref IntPtr transaction); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetLobbyUpdateTransactionMethod(IntPtr methodsPtr, Int64 lobbyId, ref IntPtr transaction); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetMemberUpdateTransactionMethod(IntPtr methodsPtr, Int64 lobbyId, Int64 userId, ref IntPtr transaction); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CreateLobbyCallback(IntPtr ptr, Result result, ref Lobby lobby); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CreateLobbyMethod(IntPtr methodsPtr, IntPtr transaction, IntPtr callbackData, CreateLobbyCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void UpdateLobbyCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void UpdateLobbyMethod(IntPtr methodsPtr, Int64 lobbyId, IntPtr transaction, IntPtr callbackData, UpdateLobbyCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void DeleteLobbyCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void DeleteLobbyMethod(IntPtr methodsPtr, Int64 lobbyId, IntPtr callbackData, DeleteLobbyCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ConnectLobbyCallback(IntPtr ptr, Result result, ref Lobby lobby); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ConnectLobbyMethod(IntPtr methodsPtr, Int64 lobbyId, [MarshalAs(UnmanagedType.LPStr)]string secret, IntPtr callbackData, ConnectLobbyCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ConnectLobbyWithActivitySecretCallback(IntPtr ptr, Result result, ref Lobby lobby); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ConnectLobbyWithActivitySecretMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)]string activitySecret, IntPtr callbackData, ConnectLobbyWithActivitySecretCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void DisconnectLobbyCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void DisconnectLobbyMethod(IntPtr methodsPtr, Int64 lobbyId, IntPtr callbackData, DisconnectLobbyCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetLobbyMethod(IntPtr methodsPtr, Int64 lobbyId, ref Lobby lobby); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetLobbyActivitySecretMethod(IntPtr methodsPtr, Int64 lobbyId, StringBuilder secret); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetLobbyMetadataValueMethod(IntPtr methodsPtr, Int64 lobbyId, [MarshalAs(UnmanagedType.LPStr)]string key, StringBuilder value); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetLobbyMetadataKeyMethod(IntPtr methodsPtr, Int64 lobbyId, Int32 index, StringBuilder key); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result LobbyMetadataCountMethod(IntPtr methodsPtr, Int64 lobbyId, ref Int32 count); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result MemberCountMethod(IntPtr methodsPtr, Int64 lobbyId, ref Int32 count); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetMemberUserIdMethod(IntPtr methodsPtr, Int64 lobbyId, Int32 index, ref Int64 userId); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetMemberUserMethod(IntPtr methodsPtr, Int64 lobbyId, Int64 userId, ref User user); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetMemberMetadataValueMethod(IntPtr methodsPtr, Int64 lobbyId, Int64 userId, [MarshalAs(UnmanagedType.LPStr)]string key, StringBuilder value); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetMemberMetadataKeyMethod(IntPtr methodsPtr, Int64 lobbyId, Int64 userId, Int32 index, StringBuilder key); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result MemberMetadataCountMethod(IntPtr methodsPtr, Int64 lobbyId, Int64 userId, ref Int32 count); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void UpdateMemberCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void UpdateMemberMethod(IntPtr methodsPtr, Int64 lobbyId, Int64 userId, IntPtr transaction, IntPtr callbackData, UpdateMemberCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SendLobbyMessageCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SendLobbyMessageMethod(IntPtr methodsPtr, Int64 lobbyId, byte[] data, Int32 dataLen, IntPtr callbackData, SendLobbyMessageCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetSearchQueryMethod(IntPtr methodsPtr, ref IntPtr query); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SearchCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SearchMethod(IntPtr methodsPtr, IntPtr query, IntPtr callbackData, SearchCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void LobbyCountMethod(IntPtr methodsPtr, ref Int32 count); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetLobbyIdMethod(IntPtr methodsPtr, Int32 index, ref Int64 lobbyId); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ConnectVoiceCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ConnectVoiceMethod(IntPtr methodsPtr, Int64 lobbyId, IntPtr callbackData, ConnectVoiceCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void DisconnectVoiceCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void DisconnectVoiceMethod(IntPtr methodsPtr, Int64 lobbyId, IntPtr callbackData, DisconnectVoiceCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result ConnectNetworkMethod(IntPtr methodsPtr, Int64 lobbyId); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result DisconnectNetworkMethod(IntPtr methodsPtr, Int64 lobbyId); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result FlushNetworkMethod(IntPtr methodsPtr); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result OpenNetworkChannelMethod(IntPtr methodsPtr, Int64 lobbyId, byte channelId, bool reliable); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result SendNetworkMessageMethod(IntPtr methodsPtr, Int64 lobbyId, Int64 userId, byte channelId, byte[] data, Int32 dataLen); + + internal GetLobbyCreateTransactionMethod GetLobbyCreateTransaction; + + internal GetLobbyUpdateTransactionMethod GetLobbyUpdateTransaction; + + internal GetMemberUpdateTransactionMethod GetMemberUpdateTransaction; + + internal CreateLobbyMethod CreateLobby; + + internal UpdateLobbyMethod UpdateLobby; + + internal DeleteLobbyMethod DeleteLobby; + + internal ConnectLobbyMethod ConnectLobby; + + internal ConnectLobbyWithActivitySecretMethod ConnectLobbyWithActivitySecret; + + internal DisconnectLobbyMethod DisconnectLobby; + + internal GetLobbyMethod GetLobby; + + internal GetLobbyActivitySecretMethod GetLobbyActivitySecret; + + internal GetLobbyMetadataValueMethod GetLobbyMetadataValue; + + internal GetLobbyMetadataKeyMethod GetLobbyMetadataKey; + + internal LobbyMetadataCountMethod LobbyMetadataCount; + + internal MemberCountMethod MemberCount; + + internal GetMemberUserIdMethod GetMemberUserId; + + internal GetMemberUserMethod GetMemberUser; + + internal GetMemberMetadataValueMethod GetMemberMetadataValue; + + internal GetMemberMetadataKeyMethod GetMemberMetadataKey; + + internal MemberMetadataCountMethod MemberMetadataCount; + + internal UpdateMemberMethod UpdateMember; + + internal SendLobbyMessageMethod SendLobbyMessage; + + internal GetSearchQueryMethod GetSearchQuery; + + internal SearchMethod Search; + + internal LobbyCountMethod LobbyCount; + + internal GetLobbyIdMethod GetLobbyId; + + internal ConnectVoiceMethod ConnectVoice; + + internal DisconnectVoiceMethod DisconnectVoice; + + internal ConnectNetworkMethod ConnectNetwork; + + internal DisconnectNetworkMethod DisconnectNetwork; + + internal FlushNetworkMethod FlushNetwork; + + internal OpenNetworkChannelMethod OpenNetworkChannel; + + internal SendNetworkMessageMethod SendNetworkMessage; + } + + public delegate void CreateLobbyHandler(Result result, ref Lobby lobby); + + public delegate void UpdateLobbyHandler(Result result); + + public delegate void DeleteLobbyHandler(Result result); + + public delegate void ConnectLobbyHandler(Result result, ref Lobby lobby); + + public delegate void ConnectLobbyWithActivitySecretHandler(Result result, ref Lobby lobby); + + public delegate void DisconnectLobbyHandler(Result result); + + public delegate void UpdateMemberHandler(Result result); + + public delegate void SendLobbyMessageHandler(Result result); + + public delegate void SearchHandler(Result result); + + public delegate void ConnectVoiceHandler(Result result); + + public delegate void DisconnectVoiceHandler(Result result); + + public delegate void LobbyUpdateHandler(Int64 lobbyId); + + public delegate void LobbyDeleteHandler(Int64 lobbyId, UInt32 reason); + + public delegate void MemberConnectHandler(Int64 lobbyId, Int64 userId); + + public delegate void MemberUpdateHandler(Int64 lobbyId, Int64 userId); + + public delegate void MemberDisconnectHandler(Int64 lobbyId, Int64 userId); + + public delegate void LobbyMessageHandler(Int64 lobbyId, Int64 userId, byte[] data); + + public delegate void SpeakingHandler(Int64 lobbyId, Int64 userId, bool speaking); + + public delegate void NetworkMessageHandler(Int64 lobbyId, Int64 userId, byte channelId, byte[] data); + + private IntPtr MethodsPtr; + + private Object MethodsStructure; + + private FFIMethods Methods + { + get + { + if (MethodsStructure == null) + { + MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods)); + } + return (FFIMethods)MethodsStructure; + } + + } + + public event LobbyUpdateHandler OnLobbyUpdate; + + public event LobbyDeleteHandler OnLobbyDelete; + + public event MemberConnectHandler OnMemberConnect; + + public event MemberUpdateHandler OnMemberUpdate; + + public event MemberDisconnectHandler OnMemberDisconnect; + + public event LobbyMessageHandler OnLobbyMessage; + + public event SpeakingHandler OnSpeaking; + + public event NetworkMessageHandler OnNetworkMessage; + + internal LobbyManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events) + { + if (eventsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + InitEvents(eventsPtr, ref events); + MethodsPtr = ptr; + if (MethodsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + } + + private void InitEvents(IntPtr eventsPtr, ref FFIEvents events) + { + events.OnLobbyUpdate = OnLobbyUpdateImpl; + events.OnLobbyDelete = OnLobbyDeleteImpl; + events.OnMemberConnect = OnMemberConnectImpl; + events.OnMemberUpdate = OnMemberUpdateImpl; + events.OnMemberDisconnect = OnMemberDisconnectImpl; + events.OnLobbyMessage = OnLobbyMessageImpl; + events.OnSpeaking = OnSpeakingImpl; + events.OnNetworkMessage = OnNetworkMessageImpl; + Marshal.StructureToPtr(events, eventsPtr, false); + } + + public LobbyTransaction GetLobbyCreateTransaction() + { + var ret = new LobbyTransaction(); + var res = Methods.GetLobbyCreateTransaction(MethodsPtr, ref ret.MethodsPtr); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public LobbyTransaction GetLobbyUpdateTransaction(Int64 lobbyId) + { + var ret = new LobbyTransaction(); + var res = Methods.GetLobbyUpdateTransaction(MethodsPtr, lobbyId, ref ret.MethodsPtr); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public LobbyMemberTransaction GetMemberUpdateTransaction(Int64 lobbyId, Int64 userId) + { + var ret = new LobbyMemberTransaction(); + var res = Methods.GetMemberUpdateTransaction(MethodsPtr, lobbyId, userId, ref ret.MethodsPtr); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + [MonoPInvokeCallback] + private static void CreateLobbyCallbackImpl(IntPtr ptr, Result result, ref Lobby lobby) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + CreateLobbyHandler callback = (CreateLobbyHandler)h.Target; + h.Free(); + callback(result, ref lobby); + } + + public void CreateLobby(LobbyTransaction transaction, CreateLobbyHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.CreateLobby(MethodsPtr, transaction.MethodsPtr, GCHandle.ToIntPtr(wrapped), CreateLobbyCallbackImpl); + transaction.MethodsPtr = IntPtr.Zero; + } + + [MonoPInvokeCallback] + private static void UpdateLobbyCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + UpdateLobbyHandler callback = (UpdateLobbyHandler)h.Target; + h.Free(); + callback(result); + } + + public void UpdateLobby(Int64 lobbyId, LobbyTransaction transaction, UpdateLobbyHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.UpdateLobby(MethodsPtr, lobbyId, transaction.MethodsPtr, GCHandle.ToIntPtr(wrapped), UpdateLobbyCallbackImpl); + transaction.MethodsPtr = IntPtr.Zero; + } + + [MonoPInvokeCallback] + private static void DeleteLobbyCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + DeleteLobbyHandler callback = (DeleteLobbyHandler)h.Target; + h.Free(); + callback(result); + } + + public void DeleteLobby(Int64 lobbyId, DeleteLobbyHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.DeleteLobby(MethodsPtr, lobbyId, GCHandle.ToIntPtr(wrapped), DeleteLobbyCallbackImpl); + } + + [MonoPInvokeCallback] + private static void ConnectLobbyCallbackImpl(IntPtr ptr, Result result, ref Lobby lobby) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + ConnectLobbyHandler callback = (ConnectLobbyHandler)h.Target; + h.Free(); + callback(result, ref lobby); + } + + public void ConnectLobby(Int64 lobbyId, string secret, ConnectLobbyHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.ConnectLobby(MethodsPtr, lobbyId, secret, GCHandle.ToIntPtr(wrapped), ConnectLobbyCallbackImpl); + } + + [MonoPInvokeCallback] + private static void ConnectLobbyWithActivitySecretCallbackImpl(IntPtr ptr, Result result, ref Lobby lobby) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + ConnectLobbyWithActivitySecretHandler callback = (ConnectLobbyWithActivitySecretHandler)h.Target; + h.Free(); + callback(result, ref lobby); + } + + public void ConnectLobbyWithActivitySecret(string activitySecret, ConnectLobbyWithActivitySecretHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.ConnectLobbyWithActivitySecret(MethodsPtr, activitySecret, GCHandle.ToIntPtr(wrapped), ConnectLobbyWithActivitySecretCallbackImpl); + } + + [MonoPInvokeCallback] + private static void DisconnectLobbyCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + DisconnectLobbyHandler callback = (DisconnectLobbyHandler)h.Target; + h.Free(); + callback(result); + } + + public void DisconnectLobby(Int64 lobbyId, DisconnectLobbyHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.DisconnectLobby(MethodsPtr, lobbyId, GCHandle.ToIntPtr(wrapped), DisconnectLobbyCallbackImpl); + } + + public Lobby GetLobby(Int64 lobbyId) + { + var ret = new Lobby(); + var res = Methods.GetLobby(MethodsPtr, lobbyId, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public string GetLobbyActivitySecret(Int64 lobbyId) + { + var ret = new StringBuilder(128); + var res = Methods.GetLobbyActivitySecret(MethodsPtr, lobbyId, ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret.ToString(); + } + + public string GetLobbyMetadataValue(Int64 lobbyId, string key) + { + var ret = new StringBuilder(4096); + var res = Methods.GetLobbyMetadataValue(MethodsPtr, lobbyId, key, ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret.ToString(); + } + + public string GetLobbyMetadataKey(Int64 lobbyId, Int32 index) + { + var ret = new StringBuilder(256); + var res = Methods.GetLobbyMetadataKey(MethodsPtr, lobbyId, index, ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret.ToString(); + } + + public Int32 LobbyMetadataCount(Int64 lobbyId) + { + var ret = new Int32(); + var res = Methods.LobbyMetadataCount(MethodsPtr, lobbyId, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public Int32 MemberCount(Int64 lobbyId) + { + var ret = new Int32(); + var res = Methods.MemberCount(MethodsPtr, lobbyId, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public Int64 GetMemberUserId(Int64 lobbyId, Int32 index) + { + var ret = new Int64(); + var res = Methods.GetMemberUserId(MethodsPtr, lobbyId, index, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public User GetMemberUser(Int64 lobbyId, Int64 userId) + { + var ret = new User(); + var res = Methods.GetMemberUser(MethodsPtr, lobbyId, userId, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public string GetMemberMetadataValue(Int64 lobbyId, Int64 userId, string key) + { + var ret = new StringBuilder(4096); + var res = Methods.GetMemberMetadataValue(MethodsPtr, lobbyId, userId, key, ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret.ToString(); + } + + public string GetMemberMetadataKey(Int64 lobbyId, Int64 userId, Int32 index) + { + var ret = new StringBuilder(256); + var res = Methods.GetMemberMetadataKey(MethodsPtr, lobbyId, userId, index, ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret.ToString(); + } + + public Int32 MemberMetadataCount(Int64 lobbyId, Int64 userId) + { + var ret = new Int32(); + var res = Methods.MemberMetadataCount(MethodsPtr, lobbyId, userId, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + [MonoPInvokeCallback] + private static void UpdateMemberCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + UpdateMemberHandler callback = (UpdateMemberHandler)h.Target; + h.Free(); + callback(result); + } + + public void UpdateMember(Int64 lobbyId, Int64 userId, LobbyMemberTransaction transaction, UpdateMemberHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.UpdateMember(MethodsPtr, lobbyId, userId, transaction.MethodsPtr, GCHandle.ToIntPtr(wrapped), UpdateMemberCallbackImpl); + transaction.MethodsPtr = IntPtr.Zero; + } + + [MonoPInvokeCallback] + private static void SendLobbyMessageCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + SendLobbyMessageHandler callback = (SendLobbyMessageHandler)h.Target; + h.Free(); + callback(result); + } + + public void SendLobbyMessage(Int64 lobbyId, byte[] data, SendLobbyMessageHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.SendLobbyMessage(MethodsPtr, lobbyId, data, data.Length, GCHandle.ToIntPtr(wrapped), SendLobbyMessageCallbackImpl); + } + + public LobbySearchQuery GetSearchQuery() + { + var ret = new LobbySearchQuery(); + var res = Methods.GetSearchQuery(MethodsPtr, ref ret.MethodsPtr); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + [MonoPInvokeCallback] + private static void SearchCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + SearchHandler callback = (SearchHandler)h.Target; + h.Free(); + callback(result); + } + + public void Search(LobbySearchQuery query, SearchHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.Search(MethodsPtr, query.MethodsPtr, GCHandle.ToIntPtr(wrapped), SearchCallbackImpl); + query.MethodsPtr = IntPtr.Zero; + } + + public Int32 LobbyCount() + { + var ret = new Int32(); + Methods.LobbyCount(MethodsPtr, ref ret); + return ret; + } + + public Int64 GetLobbyId(Int32 index) + { + var ret = new Int64(); + var res = Methods.GetLobbyId(MethodsPtr, index, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + [MonoPInvokeCallback] + private static void ConnectVoiceCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + ConnectVoiceHandler callback = (ConnectVoiceHandler)h.Target; + h.Free(); + callback(result); + } + + public void ConnectVoice(Int64 lobbyId, ConnectVoiceHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.ConnectVoice(MethodsPtr, lobbyId, GCHandle.ToIntPtr(wrapped), ConnectVoiceCallbackImpl); + } + + [MonoPInvokeCallback] + private static void DisconnectVoiceCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + DisconnectVoiceHandler callback = (DisconnectVoiceHandler)h.Target; + h.Free(); + callback(result); + } + + public void DisconnectVoice(Int64 lobbyId, DisconnectVoiceHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.DisconnectVoice(MethodsPtr, lobbyId, GCHandle.ToIntPtr(wrapped), DisconnectVoiceCallbackImpl); + } + + public void ConnectNetwork(Int64 lobbyId) + { + var res = Methods.ConnectNetwork(MethodsPtr, lobbyId); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + public void DisconnectNetwork(Int64 lobbyId) + { + var res = Methods.DisconnectNetwork(MethodsPtr, lobbyId); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + public void FlushNetwork() + { + var res = Methods.FlushNetwork(MethodsPtr); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + public void OpenNetworkChannel(Int64 lobbyId, byte channelId, bool reliable) + { + var res = Methods.OpenNetworkChannel(MethodsPtr, lobbyId, channelId, reliable); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + public void SendNetworkMessage(Int64 lobbyId, Int64 userId, byte channelId, byte[] data) + { + var res = Methods.SendNetworkMessage(MethodsPtr, lobbyId, userId, channelId, data, data.Length); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + [MonoPInvokeCallback] + private static void OnLobbyUpdateImpl(IntPtr ptr, Int64 lobbyId) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.LobbyManagerInstance.OnLobbyUpdate != null) + { + d.LobbyManagerInstance.OnLobbyUpdate.Invoke(lobbyId); + } + } + + [MonoPInvokeCallback] + private static void OnLobbyDeleteImpl(IntPtr ptr, Int64 lobbyId, UInt32 reason) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.LobbyManagerInstance.OnLobbyDelete != null) + { + d.LobbyManagerInstance.OnLobbyDelete.Invoke(lobbyId, reason); + } + } + + [MonoPInvokeCallback] + private static void OnMemberConnectImpl(IntPtr ptr, Int64 lobbyId, Int64 userId) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.LobbyManagerInstance.OnMemberConnect != null) + { + d.LobbyManagerInstance.OnMemberConnect.Invoke(lobbyId, userId); + } + } + + [MonoPInvokeCallback] + private static void OnMemberUpdateImpl(IntPtr ptr, Int64 lobbyId, Int64 userId) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.LobbyManagerInstance.OnMemberUpdate != null) + { + d.LobbyManagerInstance.OnMemberUpdate.Invoke(lobbyId, userId); + } + } + + [MonoPInvokeCallback] + private static void OnMemberDisconnectImpl(IntPtr ptr, Int64 lobbyId, Int64 userId) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.LobbyManagerInstance.OnMemberDisconnect != null) + { + d.LobbyManagerInstance.OnMemberDisconnect.Invoke(lobbyId, userId); + } + } + + [MonoPInvokeCallback] + private static void OnLobbyMessageImpl(IntPtr ptr, Int64 lobbyId, Int64 userId, IntPtr dataPtr, Int32 dataLen) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.LobbyManagerInstance.OnLobbyMessage != null) + { + byte[] data = new byte[dataLen]; + Marshal.Copy(dataPtr, data, 0, (int)dataLen); + d.LobbyManagerInstance.OnLobbyMessage.Invoke(lobbyId, userId, data); + } + } + + [MonoPInvokeCallback] + private static void OnSpeakingImpl(IntPtr ptr, Int64 lobbyId, Int64 userId, bool speaking) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.LobbyManagerInstance.OnSpeaking != null) + { + d.LobbyManagerInstance.OnSpeaking.Invoke(lobbyId, userId, speaking); + } + } + + [MonoPInvokeCallback] + private static void OnNetworkMessageImpl(IntPtr ptr, Int64 lobbyId, Int64 userId, byte channelId, IntPtr dataPtr, Int32 dataLen) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.LobbyManagerInstance.OnNetworkMessage != null) + { + byte[] data = new byte[dataLen]; + Marshal.Copy(dataPtr, data, 0, (int)dataLen); + d.LobbyManagerInstance.OnNetworkMessage.Invoke(lobbyId, userId, channelId, data); + } + } + } + + public partial class NetworkManager + { + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIEvents + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void MessageHandler(IntPtr ptr, UInt64 peerId, byte channelId, IntPtr dataPtr, Int32 dataLen); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void RouteUpdateHandler(IntPtr ptr, [MarshalAs(UnmanagedType.LPStr)]string routeData); + + internal MessageHandler OnMessage; + + internal RouteUpdateHandler OnRouteUpdate; + } + + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIMethods + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void GetPeerIdMethod(IntPtr methodsPtr, ref UInt64 peerId); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result FlushMethod(IntPtr methodsPtr); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result OpenPeerMethod(IntPtr methodsPtr, UInt64 peerId, [MarshalAs(UnmanagedType.LPStr)]string routeData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result UpdatePeerMethod(IntPtr methodsPtr, UInt64 peerId, [MarshalAs(UnmanagedType.LPStr)]string routeData); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result ClosePeerMethod(IntPtr methodsPtr, UInt64 peerId); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result OpenChannelMethod(IntPtr methodsPtr, UInt64 peerId, byte channelId, bool reliable); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result CloseChannelMethod(IntPtr methodsPtr, UInt64 peerId, byte channelId); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result SendMessageMethod(IntPtr methodsPtr, UInt64 peerId, byte channelId, byte[] data, Int32 dataLen); + + internal GetPeerIdMethod GetPeerId; + + internal FlushMethod Flush; + + internal OpenPeerMethod OpenPeer; + + internal UpdatePeerMethod UpdatePeer; + + internal ClosePeerMethod ClosePeer; + + internal OpenChannelMethod OpenChannel; + + internal CloseChannelMethod CloseChannel; + + internal SendMessageMethod SendMessage; + } + + public delegate void MessageHandler(UInt64 peerId, byte channelId, byte[] data); + + public delegate void RouteUpdateHandler(string routeData); + + private IntPtr MethodsPtr; + + private Object MethodsStructure; + + private FFIMethods Methods + { + get + { + if (MethodsStructure == null) + { + MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods)); + } + return (FFIMethods)MethodsStructure; + } + + } + + public event MessageHandler OnMessage; + + public event RouteUpdateHandler OnRouteUpdate; + + internal NetworkManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events) + { + if (eventsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + InitEvents(eventsPtr, ref events); + MethodsPtr = ptr; + if (MethodsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + } + + private void InitEvents(IntPtr eventsPtr, ref FFIEvents events) + { + events.OnMessage = OnMessageImpl; + events.OnRouteUpdate = OnRouteUpdateImpl; + Marshal.StructureToPtr(events, eventsPtr, false); + } + + /// + /// Get the local peer ID for this process. + /// + public UInt64 GetPeerId() + { + var ret = new UInt64(); + Methods.GetPeerId(MethodsPtr, ref ret); + return ret; + } + + /// + /// Send pending network messages. + /// + public void Flush() + { + var res = Methods.Flush(MethodsPtr); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + /// + /// Open a connection to a remote peer. + /// + public void OpenPeer(UInt64 peerId, string routeData) + { + var res = Methods.OpenPeer(MethodsPtr, peerId, routeData); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + /// + /// Update the route data for a connected peer. + /// + public void UpdatePeer(UInt64 peerId, string routeData) + { + var res = Methods.UpdatePeer(MethodsPtr, peerId, routeData); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + /// + /// Close the connection to a remote peer. + /// + public void ClosePeer(UInt64 peerId) + { + var res = Methods.ClosePeer(MethodsPtr, peerId); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + /// + /// Open a message channel to a connected peer. + /// + public void OpenChannel(UInt64 peerId, byte channelId, bool reliable) + { + var res = Methods.OpenChannel(MethodsPtr, peerId, channelId, reliable); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + /// + /// Close a message channel to a connected peer. + /// + public void CloseChannel(UInt64 peerId, byte channelId) + { + var res = Methods.CloseChannel(MethodsPtr, peerId, channelId); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + /// + /// Send a message to a connected peer over an opened message channel. + /// + public void SendMessage(UInt64 peerId, byte channelId, byte[] data) + { + var res = Methods.SendMessage(MethodsPtr, peerId, channelId, data, data.Length); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + [MonoPInvokeCallback] + private static void OnMessageImpl(IntPtr ptr, UInt64 peerId, byte channelId, IntPtr dataPtr, Int32 dataLen) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.NetworkManagerInstance.OnMessage != null) + { + byte[] data = new byte[dataLen]; + Marshal.Copy(dataPtr, data, 0, (int)dataLen); + d.NetworkManagerInstance.OnMessage.Invoke(peerId, channelId, data); + } + } + + [MonoPInvokeCallback] + private static void OnRouteUpdateImpl(IntPtr ptr, string routeData) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.NetworkManagerInstance.OnRouteUpdate != null) + { + d.NetworkManagerInstance.OnRouteUpdate.Invoke(routeData); + } + } + } + + public partial class OverlayManager + { + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIEvents + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ToggleHandler(IntPtr ptr, bool locked); + + internal ToggleHandler OnToggle; + } + + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIMethods + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void IsEnabledMethod(IntPtr methodsPtr, ref bool enabled); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void IsLockedMethod(IntPtr methodsPtr, ref bool locked); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SetLockedCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SetLockedMethod(IntPtr methodsPtr, bool locked, IntPtr callbackData, SetLockedCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void OpenActivityInviteCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void OpenActivityInviteMethod(IntPtr methodsPtr, ActivityActionType type, IntPtr callbackData, OpenActivityInviteCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void OpenGuildInviteCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void OpenGuildInviteMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)]string code, IntPtr callbackData, OpenGuildInviteCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void OpenVoiceSettingsCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void OpenVoiceSettingsMethod(IntPtr methodsPtr, IntPtr callbackData, OpenVoiceSettingsCallback callback); + + internal IsEnabledMethod IsEnabled; + + internal IsLockedMethod IsLocked; + + internal SetLockedMethod SetLocked; + + internal OpenActivityInviteMethod OpenActivityInvite; + + internal OpenGuildInviteMethod OpenGuildInvite; + + internal OpenVoiceSettingsMethod OpenVoiceSettings; + } + + public delegate void SetLockedHandler(Result result); + + public delegate void OpenActivityInviteHandler(Result result); + + public delegate void OpenGuildInviteHandler(Result result); + + public delegate void OpenVoiceSettingsHandler(Result result); + + public delegate void ToggleHandler(bool locked); + + private IntPtr MethodsPtr; + + private Object MethodsStructure; + + private FFIMethods Methods + { + get + { + if (MethodsStructure == null) + { + MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods)); + } + return (FFIMethods)MethodsStructure; + } + + } + + public event ToggleHandler OnToggle; + + internal OverlayManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events) + { + if (eventsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + InitEvents(eventsPtr, ref events); + MethodsPtr = ptr; + if (MethodsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + } + + private void InitEvents(IntPtr eventsPtr, ref FFIEvents events) + { + events.OnToggle = OnToggleImpl; + Marshal.StructureToPtr(events, eventsPtr, false); + } + + public bool IsEnabled() + { + var ret = new bool(); + Methods.IsEnabled(MethodsPtr, ref ret); + return ret; + } + + public bool IsLocked() + { + var ret = new bool(); + Methods.IsLocked(MethodsPtr, ref ret); + return ret; + } + + [MonoPInvokeCallback] + private static void SetLockedCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + SetLockedHandler callback = (SetLockedHandler)h.Target; + h.Free(); + callback(result); + } + + public void SetLocked(bool locked, SetLockedHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.SetLocked(MethodsPtr, locked, GCHandle.ToIntPtr(wrapped), SetLockedCallbackImpl); + } + + [MonoPInvokeCallback] + private static void OpenActivityInviteCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + OpenActivityInviteHandler callback = (OpenActivityInviteHandler)h.Target; + h.Free(); + callback(result); + } + + public void OpenActivityInvite(ActivityActionType type, OpenActivityInviteHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.OpenActivityInvite(MethodsPtr, type, GCHandle.ToIntPtr(wrapped), OpenActivityInviteCallbackImpl); + } + + [MonoPInvokeCallback] + private static void OpenGuildInviteCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + OpenGuildInviteHandler callback = (OpenGuildInviteHandler)h.Target; + h.Free(); + callback(result); + } + + public void OpenGuildInvite(string code, OpenGuildInviteHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.OpenGuildInvite(MethodsPtr, code, GCHandle.ToIntPtr(wrapped), OpenGuildInviteCallbackImpl); + } + + [MonoPInvokeCallback] + private static void OpenVoiceSettingsCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + OpenVoiceSettingsHandler callback = (OpenVoiceSettingsHandler)h.Target; + h.Free(); + callback(result); + } + + public void OpenVoiceSettings(OpenVoiceSettingsHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.OpenVoiceSettings(MethodsPtr, GCHandle.ToIntPtr(wrapped), OpenVoiceSettingsCallbackImpl); + } + + [MonoPInvokeCallback] + private static void OnToggleImpl(IntPtr ptr, bool locked) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.OverlayManagerInstance.OnToggle != null) + { + d.OverlayManagerInstance.OnToggle.Invoke(locked); + } + } + } + + public partial class StorageManager + { + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIEvents + { + + } + + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIMethods + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result ReadMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)]string name, byte[] data, Int32 dataLen, ref UInt32 read); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ReadAsyncCallback(IntPtr ptr, Result result, IntPtr dataPtr, Int32 dataLen); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ReadAsyncMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)]string name, IntPtr callbackData, ReadAsyncCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ReadAsyncPartialCallback(IntPtr ptr, Result result, IntPtr dataPtr, Int32 dataLen); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void ReadAsyncPartialMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)]string name, UInt64 offset, UInt64 length, IntPtr callbackData, ReadAsyncPartialCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result WriteMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)]string name, byte[] data, Int32 dataLen); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void WriteAsyncCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void WriteAsyncMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)]string name, byte[] data, Int32 dataLen, IntPtr callbackData, WriteAsyncCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result DeleteMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)]string name); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result ExistsMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)]string name, ref bool exists); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CountMethod(IntPtr methodsPtr, ref Int32 count); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result StatMethod(IntPtr methodsPtr, [MarshalAs(UnmanagedType.LPStr)]string name, ref FileStat stat); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result StatAtMethod(IntPtr methodsPtr, Int32 index, ref FileStat stat); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetPathMethod(IntPtr methodsPtr, StringBuilder path); + + internal ReadMethod Read; + + internal ReadAsyncMethod ReadAsync; + + internal ReadAsyncPartialMethod ReadAsyncPartial; + + internal WriteMethod Write; + + internal WriteAsyncMethod WriteAsync; + + internal DeleteMethod Delete; + + internal ExistsMethod Exists; + + internal CountMethod Count; + + internal StatMethod Stat; + + internal StatAtMethod StatAt; + + internal GetPathMethod GetPath; + } + + public delegate void ReadAsyncHandler(Result result, byte[] data); + + public delegate void ReadAsyncPartialHandler(Result result, byte[] data); + + public delegate void WriteAsyncHandler(Result result); + + private IntPtr MethodsPtr; + + private Object MethodsStructure; + + private FFIMethods Methods + { + get + { + if (MethodsStructure == null) + { + MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods)); + } + return (FFIMethods)MethodsStructure; + } + + } + + internal StorageManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events) + { + if (eventsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + InitEvents(eventsPtr, ref events); + MethodsPtr = ptr; + if (MethodsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + } + + private void InitEvents(IntPtr eventsPtr, ref FFIEvents events) + { + Marshal.StructureToPtr(events, eventsPtr, false); + } + + public UInt32 Read(string name, byte[] data) + { + var ret = new UInt32(); + var res = Methods.Read(MethodsPtr, name, data, data.Length, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + [MonoPInvokeCallback] + private static void ReadAsyncCallbackImpl(IntPtr ptr, Result result, IntPtr dataPtr, Int32 dataLen) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + ReadAsyncHandler callback = (ReadAsyncHandler)h.Target; + h.Free(); + byte[] data = new byte[dataLen]; + Marshal.Copy(dataPtr, data, 0, (int)dataLen); + callback(result, data); + } + + public void ReadAsync(string name, ReadAsyncHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.ReadAsync(MethodsPtr, name, GCHandle.ToIntPtr(wrapped), ReadAsyncCallbackImpl); + } + + [MonoPInvokeCallback] + private static void ReadAsyncPartialCallbackImpl(IntPtr ptr, Result result, IntPtr dataPtr, Int32 dataLen) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + ReadAsyncPartialHandler callback = (ReadAsyncPartialHandler)h.Target; + h.Free(); + byte[] data = new byte[dataLen]; + Marshal.Copy(dataPtr, data, 0, (int)dataLen); + callback(result, data); + } + + public void ReadAsyncPartial(string name, UInt64 offset, UInt64 length, ReadAsyncPartialHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.ReadAsyncPartial(MethodsPtr, name, offset, length, GCHandle.ToIntPtr(wrapped), ReadAsyncPartialCallbackImpl); + } + + public void Write(string name, byte[] data) + { + var res = Methods.Write(MethodsPtr, name, data, data.Length); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + [MonoPInvokeCallback] + private static void WriteAsyncCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + WriteAsyncHandler callback = (WriteAsyncHandler)h.Target; + h.Free(); + callback(result); + } + + public void WriteAsync(string name, byte[] data, WriteAsyncHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.WriteAsync(MethodsPtr, name, data, data.Length, GCHandle.ToIntPtr(wrapped), WriteAsyncCallbackImpl); + } + + public void Delete(string name) + { + var res = Methods.Delete(MethodsPtr, name); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + public bool Exists(string name) + { + var ret = new bool(); + var res = Methods.Exists(MethodsPtr, name, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public Int32 Count() + { + var ret = new Int32(); + Methods.Count(MethodsPtr, ref ret); + return ret; + } + + public FileStat Stat(string name) + { + var ret = new FileStat(); + var res = Methods.Stat(MethodsPtr, name, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public FileStat StatAt(Int32 index) + { + var ret = new FileStat(); + var res = Methods.StatAt(MethodsPtr, index, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public string GetPath() + { + var ret = new StringBuilder(4096); + var res = Methods.GetPath(MethodsPtr, ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret.ToString(); + } + } + + public partial class StoreManager + { + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIEvents + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void EntitlementCreateHandler(IntPtr ptr, ref Entitlement entitlement); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void EntitlementDeleteHandler(IntPtr ptr, ref Entitlement entitlement); + + internal EntitlementCreateHandler OnEntitlementCreate; + + internal EntitlementDeleteHandler OnEntitlementDelete; + } + + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIMethods + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void FetchSkusCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void FetchSkusMethod(IntPtr methodsPtr, IntPtr callbackData, FetchSkusCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CountSkusMethod(IntPtr methodsPtr, ref Int32 count); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetSkuMethod(IntPtr methodsPtr, Int64 skuId, ref Sku sku); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetSkuAtMethod(IntPtr methodsPtr, Int32 index, ref Sku sku); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void FetchEntitlementsCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void FetchEntitlementsMethod(IntPtr methodsPtr, IntPtr callbackData, FetchEntitlementsCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CountEntitlementsMethod(IntPtr methodsPtr, ref Int32 count); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetEntitlementMethod(IntPtr methodsPtr, Int64 entitlementId, ref Entitlement entitlement); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetEntitlementAtMethod(IntPtr methodsPtr, Int32 index, ref Entitlement entitlement); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result HasSkuEntitlementMethod(IntPtr methodsPtr, Int64 skuId, ref bool hasEntitlement); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void StartPurchaseCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void StartPurchaseMethod(IntPtr methodsPtr, Int64 skuId, IntPtr callbackData, StartPurchaseCallback callback); + + internal FetchSkusMethod FetchSkus; + + internal CountSkusMethod CountSkus; + + internal GetSkuMethod GetSku; + + internal GetSkuAtMethod GetSkuAt; + + internal FetchEntitlementsMethod FetchEntitlements; + + internal CountEntitlementsMethod CountEntitlements; + + internal GetEntitlementMethod GetEntitlement; + + internal GetEntitlementAtMethod GetEntitlementAt; + + internal HasSkuEntitlementMethod HasSkuEntitlement; + + internal StartPurchaseMethod StartPurchase; + } + + public delegate void FetchSkusHandler(Result result); + + public delegate void FetchEntitlementsHandler(Result result); + + public delegate void StartPurchaseHandler(Result result); + + public delegate void EntitlementCreateHandler(ref Entitlement entitlement); + + public delegate void EntitlementDeleteHandler(ref Entitlement entitlement); + + private IntPtr MethodsPtr; + + private Object MethodsStructure; + + private FFIMethods Methods + { + get + { + if (MethodsStructure == null) + { + MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods)); + } + return (FFIMethods)MethodsStructure; + } + + } + + public event EntitlementCreateHandler OnEntitlementCreate; + + public event EntitlementDeleteHandler OnEntitlementDelete; + + internal StoreManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events) + { + if (eventsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + InitEvents(eventsPtr, ref events); + MethodsPtr = ptr; + if (MethodsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + } + + private void InitEvents(IntPtr eventsPtr, ref FFIEvents events) + { + events.OnEntitlementCreate = OnEntitlementCreateImpl; + events.OnEntitlementDelete = OnEntitlementDeleteImpl; + Marshal.StructureToPtr(events, eventsPtr, false); + } + + [MonoPInvokeCallback] + private static void FetchSkusCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + FetchSkusHandler callback = (FetchSkusHandler)h.Target; + h.Free(); + callback(result); + } + + public void FetchSkus(FetchSkusHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.FetchSkus(MethodsPtr, GCHandle.ToIntPtr(wrapped), FetchSkusCallbackImpl); + } + + public Int32 CountSkus() + { + var ret = new Int32(); + Methods.CountSkus(MethodsPtr, ref ret); + return ret; + } + + public Sku GetSku(Int64 skuId) + { + var ret = new Sku(); + var res = Methods.GetSku(MethodsPtr, skuId, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public Sku GetSkuAt(Int32 index) + { + var ret = new Sku(); + var res = Methods.GetSkuAt(MethodsPtr, index, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + [MonoPInvokeCallback] + private static void FetchEntitlementsCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + FetchEntitlementsHandler callback = (FetchEntitlementsHandler)h.Target; + h.Free(); + callback(result); + } + + public void FetchEntitlements(FetchEntitlementsHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.FetchEntitlements(MethodsPtr, GCHandle.ToIntPtr(wrapped), FetchEntitlementsCallbackImpl); + } + + public Int32 CountEntitlements() + { + var ret = new Int32(); + Methods.CountEntitlements(MethodsPtr, ref ret); + return ret; + } + + public Entitlement GetEntitlement(Int64 entitlementId) + { + var ret = new Entitlement(); + var res = Methods.GetEntitlement(MethodsPtr, entitlementId, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public Entitlement GetEntitlementAt(Int32 index) + { + var ret = new Entitlement(); + var res = Methods.GetEntitlementAt(MethodsPtr, index, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public bool HasSkuEntitlement(Int64 skuId) + { + var ret = new bool(); + var res = Methods.HasSkuEntitlement(MethodsPtr, skuId, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + [MonoPInvokeCallback] + private static void StartPurchaseCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + StartPurchaseHandler callback = (StartPurchaseHandler)h.Target; + h.Free(); + callback(result); + } + + public void StartPurchase(Int64 skuId, StartPurchaseHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.StartPurchase(MethodsPtr, skuId, GCHandle.ToIntPtr(wrapped), StartPurchaseCallbackImpl); + } + + [MonoPInvokeCallback] + private static void OnEntitlementCreateImpl(IntPtr ptr, ref Entitlement entitlement) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.StoreManagerInstance.OnEntitlementCreate != null) + { + d.StoreManagerInstance.OnEntitlementCreate.Invoke(ref entitlement); + } + } + + [MonoPInvokeCallback] + private static void OnEntitlementDeleteImpl(IntPtr ptr, ref Entitlement entitlement) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.StoreManagerInstance.OnEntitlementDelete != null) + { + d.StoreManagerInstance.OnEntitlementDelete.Invoke(ref entitlement); + } + } + } + + public partial class VoiceManager + { + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIEvents + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SettingsUpdateHandler(IntPtr ptr); + + internal SettingsUpdateHandler OnSettingsUpdate; + } + + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIMethods + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetInputModeMethod(IntPtr methodsPtr, ref InputMode inputMode); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SetInputModeCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SetInputModeMethod(IntPtr methodsPtr, InputMode inputMode, IntPtr callbackData, SetInputModeCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result IsSelfMuteMethod(IntPtr methodsPtr, ref bool mute); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result SetSelfMuteMethod(IntPtr methodsPtr, bool mute); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result IsSelfDeafMethod(IntPtr methodsPtr, ref bool deaf); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result SetSelfDeafMethod(IntPtr methodsPtr, bool deaf); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result IsLocalMuteMethod(IntPtr methodsPtr, Int64 userId, ref bool mute); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result SetLocalMuteMethod(IntPtr methodsPtr, Int64 userId, bool mute); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetLocalVolumeMethod(IntPtr methodsPtr, Int64 userId, ref byte volume); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result SetLocalVolumeMethod(IntPtr methodsPtr, Int64 userId, byte volume); + + internal GetInputModeMethod GetInputMode; + + internal SetInputModeMethod SetInputMode; + + internal IsSelfMuteMethod IsSelfMute; + + internal SetSelfMuteMethod SetSelfMute; + + internal IsSelfDeafMethod IsSelfDeaf; + + internal SetSelfDeafMethod SetSelfDeaf; + + internal IsLocalMuteMethod IsLocalMute; + + internal SetLocalMuteMethod SetLocalMute; + + internal GetLocalVolumeMethod GetLocalVolume; + + internal SetLocalVolumeMethod SetLocalVolume; + } + + public delegate void SetInputModeHandler(Result result); + + public delegate void SettingsUpdateHandler(); + + private IntPtr MethodsPtr; + + private Object MethodsStructure; + + private FFIMethods Methods + { + get + { + if (MethodsStructure == null) + { + MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods)); + } + return (FFIMethods)MethodsStructure; + } + + } + + public event SettingsUpdateHandler OnSettingsUpdate; + + internal VoiceManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events) + { + if (eventsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + InitEvents(eventsPtr, ref events); + MethodsPtr = ptr; + if (MethodsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + } + + private void InitEvents(IntPtr eventsPtr, ref FFIEvents events) + { + events.OnSettingsUpdate = OnSettingsUpdateImpl; + Marshal.StructureToPtr(events, eventsPtr, false); + } + + public InputMode GetInputMode() + { + var ret = new InputMode(); + var res = Methods.GetInputMode(MethodsPtr, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + [MonoPInvokeCallback] + private static void SetInputModeCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + SetInputModeHandler callback = (SetInputModeHandler)h.Target; + h.Free(); + callback(result); + } + + public void SetInputMode(InputMode inputMode, SetInputModeHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.SetInputMode(MethodsPtr, inputMode, GCHandle.ToIntPtr(wrapped), SetInputModeCallbackImpl); + } + + public bool IsSelfMute() + { + var ret = new bool(); + var res = Methods.IsSelfMute(MethodsPtr, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public void SetSelfMute(bool mute) + { + var res = Methods.SetSelfMute(MethodsPtr, mute); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + public bool IsSelfDeaf() + { + var ret = new bool(); + var res = Methods.IsSelfDeaf(MethodsPtr, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public void SetSelfDeaf(bool deaf) + { + var res = Methods.SetSelfDeaf(MethodsPtr, deaf); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + public bool IsLocalMute(Int64 userId) + { + var ret = new bool(); + var res = Methods.IsLocalMute(MethodsPtr, userId, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public void SetLocalMute(Int64 userId, bool mute) + { + var res = Methods.SetLocalMute(MethodsPtr, userId, mute); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + public byte GetLocalVolume(Int64 userId) + { + var ret = new byte(); + var res = Methods.GetLocalVolume(MethodsPtr, userId, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public void SetLocalVolume(Int64 userId, byte volume) + { + var res = Methods.SetLocalVolume(MethodsPtr, userId, volume); + if (res != Result.Ok) + { + throw new ResultException(res); + } + } + + [MonoPInvokeCallback] + private static void OnSettingsUpdateImpl(IntPtr ptr) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.VoiceManagerInstance.OnSettingsUpdate != null) + { + d.VoiceManagerInstance.OnSettingsUpdate.Invoke(); + } + } + } + + public partial class AchievementManager + { + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIEvents + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void UserAchievementUpdateHandler(IntPtr ptr, ref UserAchievement userAchievement); + + internal UserAchievementUpdateHandler OnUserAchievementUpdate; + } + + [StructLayout(LayoutKind.Sequential)] + internal partial struct FFIMethods + { + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SetUserAchievementCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void SetUserAchievementMethod(IntPtr methodsPtr, Int64 achievementId, byte percentComplete, IntPtr callbackData, SetUserAchievementCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void FetchUserAchievementsCallback(IntPtr ptr, Result result); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void FetchUserAchievementsMethod(IntPtr methodsPtr, IntPtr callbackData, FetchUserAchievementsCallback callback); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate void CountUserAchievementsMethod(IntPtr methodsPtr, ref Int32 count); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetUserAchievementMethod(IntPtr methodsPtr, Int64 userAchievementId, ref UserAchievement userAchievement); + + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + internal delegate Result GetUserAchievementAtMethod(IntPtr methodsPtr, Int32 index, ref UserAchievement userAchievement); + + internal SetUserAchievementMethod SetUserAchievement; + + internal FetchUserAchievementsMethod FetchUserAchievements; + + internal CountUserAchievementsMethod CountUserAchievements; + + internal GetUserAchievementMethod GetUserAchievement; + + internal GetUserAchievementAtMethod GetUserAchievementAt; + } + + public delegate void SetUserAchievementHandler(Result result); + + public delegate void FetchUserAchievementsHandler(Result result); + + public delegate void UserAchievementUpdateHandler(ref UserAchievement userAchievement); + + private IntPtr MethodsPtr; + + private Object MethodsStructure; + + private FFIMethods Methods + { + get + { + if (MethodsStructure == null) + { + MethodsStructure = Marshal.PtrToStructure(MethodsPtr, typeof(FFIMethods)); + } + return (FFIMethods)MethodsStructure; + } + + } + + public event UserAchievementUpdateHandler OnUserAchievementUpdate; + + internal AchievementManager(IntPtr ptr, IntPtr eventsPtr, ref FFIEvents events) + { + if (eventsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + InitEvents(eventsPtr, ref events); + MethodsPtr = ptr; + if (MethodsPtr == IntPtr.Zero) { + throw new ResultException(Result.InternalError); + } + } + + private void InitEvents(IntPtr eventsPtr, ref FFIEvents events) + { + events.OnUserAchievementUpdate = OnUserAchievementUpdateImpl; + Marshal.StructureToPtr(events, eventsPtr, false); + } + + [MonoPInvokeCallback] + private static void SetUserAchievementCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + SetUserAchievementHandler callback = (SetUserAchievementHandler)h.Target; + h.Free(); + callback(result); + } + + public void SetUserAchievement(Int64 achievementId, byte percentComplete, SetUserAchievementHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.SetUserAchievement(MethodsPtr, achievementId, percentComplete, GCHandle.ToIntPtr(wrapped), SetUserAchievementCallbackImpl); + } + + [MonoPInvokeCallback] + private static void FetchUserAchievementsCallbackImpl(IntPtr ptr, Result result) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + FetchUserAchievementsHandler callback = (FetchUserAchievementsHandler)h.Target; + h.Free(); + callback(result); + } + + public void FetchUserAchievements(FetchUserAchievementsHandler callback) + { + GCHandle wrapped = GCHandle.Alloc(callback); + Methods.FetchUserAchievements(MethodsPtr, GCHandle.ToIntPtr(wrapped), FetchUserAchievementsCallbackImpl); + } + + public Int32 CountUserAchievements() + { + var ret = new Int32(); + Methods.CountUserAchievements(MethodsPtr, ref ret); + return ret; + } + + public UserAchievement GetUserAchievement(Int64 userAchievementId) + { + var ret = new UserAchievement(); + var res = Methods.GetUserAchievement(MethodsPtr, userAchievementId, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + public UserAchievement GetUserAchievementAt(Int32 index) + { + var ret = new UserAchievement(); + var res = Methods.GetUserAchievementAt(MethodsPtr, index, ref ret); + if (res != Result.Ok) + { + throw new ResultException(res); + } + return ret; + } + + [MonoPInvokeCallback] + private static void OnUserAchievementUpdateImpl(IntPtr ptr, ref UserAchievement userAchievement) + { + GCHandle h = GCHandle.FromIntPtr(ptr); + Discord d = (Discord)h.Target; + if (d.AchievementManagerInstance.OnUserAchievementUpdate != null) + { + d.AchievementManagerInstance.OnUserAchievementUpdate.Invoke(ref userAchievement); + } + } + } +} diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/Core.cs.meta b/Assets/ERP/Editor/Plugins/DiscordSDK/Core.cs.meta new file mode 100644 index 0000000..5ec099f --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/Core.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: e67fa7bdd3cf6a34e9ef9b85b66e7f0a +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/ImageManager.cs b/Assets/ERP/Editor/Plugins/DiscordSDK/ImageManager.cs new file mode 100644 index 0000000..d00cd4e --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/ImageManager.cs @@ -0,0 +1,53 @@ +using System; +using System.Runtime.InteropServices; +#if UNITY_EDITOR || UNITY_STANDALONE +using UnityEngine; +#endif + +namespace ERP.Discord +{ + public partial struct ImageHandle + { + static public ImageHandle User(Int64 id) + { + return User(id, 128); + } + + static public ImageHandle User(Int64 id, UInt32 size) + { + return new ImageHandle + { + Type = ImageType.User, + Id = id, + Size = size, + }; + } + } + + public partial class ImageManager + { + public void Fetch(ImageHandle handle, FetchHandler callback) + { + Fetch(handle, false, callback); + } + + public byte[] GetData(ImageHandle handle) + { + var dimensions = GetDimensions(handle); + var data = new byte[dimensions.Width * dimensions.Height * 4]; + GetData(handle, data); + return data; + } + +#if UNITY_EDITOR || UNITY_STANDALONE + public Texture2D GetTexture(ImageHandle handle) + { + var dimensions = GetDimensions(handle); + var texture = new Texture2D((int)dimensions.Width, (int)dimensions.Height, TextureFormat.RGBA32, false, true); + texture.LoadRawTextureData(GetData(handle)); + texture.Apply(); + return texture; + } +#endif + } +} diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/ImageManager.cs.meta b/Assets/ERP/Editor/Plugins/DiscordSDK/ImageManager.cs.meta new file mode 100644 index 0000000..419ca56 --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/ImageManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: a07e195a8d9505745a5ffd0ba2bb01e2 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/LobbyManager.cs b/Assets/ERP/Editor/Plugins/DiscordSDK/LobbyManager.cs new file mode 100644 index 0000000..17292a5 --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/LobbyManager.cs @@ -0,0 +1,26 @@ +using System; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.Text; + +namespace ERP.Discord +{ + public partial class LobbyManager + { + public IEnumerable GetMemberUsers(Int64 lobbyID) + { + var memberCount = MemberCount(lobbyID); + var members = new List(); + for (var i = 0; i < memberCount; i++) + { + members.Add(GetMemberUser(lobbyID, GetMemberUserId(lobbyID, i))); + } + return members; + } + + public void SendLobbyMessage(Int64 lobbyID, string data, SendLobbyMessageHandler handler) + { + SendLobbyMessage(lobbyID, Encoding.UTF8.GetBytes(data), handler); + } + } +} diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/LobbyManager.cs.meta b/Assets/ERP/Editor/Plugins/DiscordSDK/LobbyManager.cs.meta new file mode 100644 index 0000000..1927a55 --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/LobbyManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: d033386aa12b5434890ecd02dfb2486d +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/StorageManager.cs b/Assets/ERP/Editor/Plugins/DiscordSDK/StorageManager.cs new file mode 100644 index 0000000..3ccc511 --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/StorageManager.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace ERP.Discord +{ + public partial class StorageManager + { + public IEnumerable Files() + { + var fileCount = Count(); + var files = new List(); + for (var i = 0; i < fileCount; i++) + { + files.Add(StatAt(i)); + } + return files; + } + } +} diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/StorageManager.cs.meta b/Assets/ERP/Editor/Plugins/DiscordSDK/StorageManager.cs.meta new file mode 100644 index 0000000..d7efa70 --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/StorageManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: f117fb9d4ace5c34b8fd8cc721cca726 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/StoreManager.cs b/Assets/ERP/Editor/Plugins/DiscordSDK/StoreManager.cs new file mode 100644 index 0000000..f8a1721 --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/StoreManager.cs @@ -0,0 +1,32 @@ +using System; +using System.Runtime.InteropServices; +using System.Collections.Generic; +using System.Text; + +namespace ERP.Discord +{ + public partial class StoreManager + { + public IEnumerable GetEntitlements() + { + var count = CountEntitlements(); + var entitlements = new List(); + for (var i = 0; i < count; i++) + { + entitlements.Add(GetEntitlementAt(i)); + } + return entitlements; + } + + public IEnumerable GetSkus() + { + var count = CountSkus(); + var skus = new List(); + for (var i = 0; i < count; i++) + { + skus.Add(GetSkuAt(i)); + } + return skus; + } + } +} diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/StoreManager.cs.meta b/Assets/ERP/Editor/Plugins/DiscordSDK/StoreManager.cs.meta new file mode 100644 index 0000000..114ebb1 --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/StoreManager.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 88ddef408c40a034fb598224080b36e7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/x86.meta b/Assets/ERP/Editor/Plugins/DiscordSDK/x86.meta new file mode 100644 index 0000000..c5740eb --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/x86.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 6cf4f21b3c4cef54ebba8baf75884671 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/x86/discord_game_sdk.dll b/Assets/ERP/Editor/Plugins/DiscordSDK/x86/discord_game_sdk.dll new file mode 100644 index 0000000..4a0bb1b --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/x86/discord_game_sdk.dll @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:d8e7d9feb3de8482b186ae44fd1c9abb41fe2b3b3d2c7cd3a4d742ebbad30cdf +size 3154744 diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/x86/discord_game_sdk.dll.meta b/Assets/ERP/Editor/Plugins/DiscordSDK/x86/discord_game_sdk.dll.meta new file mode 100644 index 0000000..ffa3442 --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/x86/discord_game_sdk.dll.meta @@ -0,0 +1,80 @@ +fileFormatVersion: 2 +guid: 7cc1a84a3fca5524cb7bcb73f7c1aabd +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: x86 + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/x86_64.meta b/Assets/ERP/Editor/Plugins/DiscordSDK/x86_64.meta new file mode 100644 index 0000000..1346933 --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/x86_64.meta @@ -0,0 +1,8 @@ +fileFormatVersion: 2 +guid: 050e0629584e2d54cbf84f0e0ed91c69 +folderAsset: yes +DefaultImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/x86_64/discord_game_sdk.dll b/Assets/ERP/Editor/Plugins/DiscordSDK/x86_64/discord_game_sdk.dll new file mode 100644 index 0000000..1117f05 --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/x86_64/discord_game_sdk.dll @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:527768710ddb0953fce5eb1700c2566b6451135d76f1d0610b63907cd5ba94c5 +size 3891512 diff --git a/Assets/ERP/Editor/Plugins/DiscordSDK/x86_64/discord_game_sdk.dll.meta b/Assets/ERP/Editor/Plugins/DiscordSDK/x86_64/discord_game_sdk.dll.meta new file mode 100644 index 0000000..457e136 --- /dev/null +++ b/Assets/ERP/Editor/Plugins/DiscordSDK/x86_64/discord_game_sdk.dll.meta @@ -0,0 +1,80 @@ +fileFormatVersion: 2 +guid: 1727ecd695a502444b36efd0e5dacd34 +PluginImporter: + externalObjects: {} + serializedVersion: 2 + iconMap: {} + executionOrder: {} + isPreloaded: 0 + isOverridable: 0 + platformData: + - first: + '': Any + second: + enabled: 0 + settings: + Exclude Editor: 0 + Exclude Linux: 1 + Exclude Linux64: 1 + Exclude LinuxUniversal: 1 + Exclude OSXUniversal: 1 + Exclude Win: 1 + Exclude Win64: 1 + - first: + Any: + second: + enabled: 0 + settings: {} + - first: + Editor: Editor + second: + enabled: 1 + settings: + CPU: x86_64 + DefaultValueInitialized: true + OS: AnyOS + - first: + Facebook: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Facebook: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Linux + second: + enabled: 0 + settings: + CPU: x86 + - first: + Standalone: Linux64 + second: + enabled: 0 + settings: + CPU: x86_64 + - first: + Standalone: OSXUniversal + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win + second: + enabled: 0 + settings: + CPU: AnyCPU + - first: + Standalone: Win64 + second: + enabled: 0 + settings: + CPU: AnyCPU + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/Editor/com.ben-w.erp.asmdef b/Assets/ERP/Editor/com.ben-w.erp.asmdef new file mode 100644 index 0000000..c041a3c --- /dev/null +++ b/Assets/ERP/Editor/com.ben-w.erp.asmdef @@ -0,0 +1,13 @@ +{ + "name": "com.ben-w.erp", + "references": [], + "includePlatforms": [], + "excludePlatforms": [], + "allowUnsafeCode": false, + "overrideReferences": false, + "precompiledReferences": [], + "autoReferenced": true, + "defineConstraints": [], + "versionDefines": [], + "noEngineReferences": false +} \ No newline at end of file diff --git a/Assets/ERP/Editor/com.ben-w.erp.asmdef.meta b/Assets/ERP/Editor/com.ben-w.erp.asmdef.meta new file mode 100644 index 0000000..5fd5a09 --- /dev/null +++ b/Assets/ERP/Editor/com.ben-w.erp.asmdef.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 5f94b3bb5603bb5489cba7d6df77444c +AssemblyDefinitionImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/README.md b/Assets/ERP/README.md new file mode 100644 index 0000000..f7ec115 --- /dev/null +++ b/Assets/ERP/README.md @@ -0,0 +1,16 @@ +# Editor Rich Presence +## A Discord Rich Presence for the Unity editor + +![Unity Asset Store Image](https://assetstorev1-prd-cdn.unity3d.com/key-image/d514aa2a-ca58-4a63-9ae0-b27239e1f8d8.webp) + +Show off what you're working on in unity with Editor Rich Presence on discord. + +![Example Image](https://assetstorev1-prd-cdn.unity3d.com/package-screenshot/d7c67997-ea03-4881-ae7c-41f15296513a.webp) + +## Download + +You can now download Editor Rich Presence from the Unity Asset store from [here](https://assetstore.unity.com/packages/tools/utilities/editor-rich-presence-178736)! + +## Warning + +This package makes a `.erp` file in the root of the project if you don't want this to be shared in a git repo add it to your ignore list. diff --git a/Assets/ERP/README.md.meta b/Assets/ERP/README.md.meta new file mode 100644 index 0000000..5672cf0 --- /dev/null +++ b/Assets/ERP/README.md.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: 7236ea587e9df0b4eb4779968f15f94f +TextScriptImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: diff --git a/Assets/ERP/package.json b/Assets/ERP/package.json new file mode 100644 index 0000000..6081887 --- /dev/null +++ b/Assets/ERP/package.json @@ -0,0 +1,17 @@ +{ + "name": "com.ben-w.erp", + "version": "3.1.2", + "displayName": "Editor Rich Presence", + "description": "Show off what you're working on in Unity with Editor Rich Presence on discord.\n\nEditor Rich Presence uses Discords GameSDK to display your project name, current active scene name and session time on your Discord profile. These can be disabled on a per-project basis.", + "keywords": [ + "Discord", + "Rich Presense", + "Editor Tool" + ], + "author": { + "name": "Ben Wilson", + "email": "me@ben-w.com", + "url": "https://github.com/MarshMello0/Editor-Rich-Presence" + }, + "type": "tool" +} \ No newline at end of file diff --git a/Assets/ERP/package.json.meta b/Assets/ERP/package.json.meta new file mode 100644 index 0000000..70925c2 --- /dev/null +++ b/Assets/ERP/package.json.meta @@ -0,0 +1,7 @@ +fileFormatVersion: 2 +guid: d6c6f38634ca76649b31df0c339545c0 +PackageManifestImporter: + externalObjects: {} + userData: + assetBundleName: + assetBundleVariant: