Decompiled source of DiscordRichPresence v1.2.1
Cuno-DiscordRichPresence-1.2.1/DiscordRichPresence.dll
Decompiled 2 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using DiscordRPC; using DiscordRPC.Events; using DiscordRPC.IO; using DiscordRPC.Logging; using DiscordRPC.Message; using DiscordRPC.Unity; using DiscordRichPresence.Hooks; using DiscordRichPresence.Utils; using Epic.OnlineServices; using Epic.OnlineServices.Lobby; using Facepunch.Steamworks; using Lachee.IO; using Microsoft.CodeAnalysis; using On.RoR2; using On.RoR2.UI.MainMenu; using R2API.Utils; using RiskOfOptions; using RiskOfOptions.Options; using RoR2; using RoR2.UI.MainMenu; using UnityEngine; using UnityEngine.SceneManagement; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")] [assembly: AssemblyCompany("DiscordRichPresence")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+a2e8600d5beff9c3044c98e2f0d9d1d6a8693463")] [assembly: AssemblyProduct("DiscordRichPresence")] [assembly: AssemblyTitle("DiscordRichPresence")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace DiscordRPC.Unity { public class UnityNamedPipe : INamedPipeClient, IDisposable { private const string PIPE_NAME = "discord-ipc-{0}"; private NamedPipeClientStream _stream; private readonly byte[] _buffer = new byte[PipeFrame.MAX_SIZE]; private volatile bool _isDisposed; public ILogger Logger { get; set; } public bool IsConnected => _stream != null && _stream.IsConnected; public int ConnectedPipe { get; private set; } public bool Connect(int pipe) { if (_isDisposed) { throw new ObjectDisposedException("NamedPipe"); } if (pipe > 9) { throw new ArgumentOutOfRangeException("pipe", "Argument cannot be greater than 9"); } if (pipe < 0) { for (int i = 0; i < 10; i++) { if (AttemptConnection(i) || AttemptConnection(i, doSandbox: true)) { return true; } } return false; } return AttemptConnection(pipe) || AttemptConnection(pipe, doSandbox: true); } private bool AttemptConnection(int pipe, bool doSandbox = false) { //IL_00f0: Unknown result type (might be due to invalid IL or missing references) //IL_00fa: Expected O, but got Unknown if (_stream != null) { Logger.Error("Attempted to create a new stream while one already exists!", Array.Empty<object>()); return false; } if (IsConnected) { Logger.Error("Attempted to create a new connection while one already exists!", Array.Empty<object>()); return false; } try { string text = (doSandbox ? GetPipeSandbox() : ""); if (doSandbox && text == null) { Logger.Trace("Skipping sandbox because this platform does not support it", Array.Empty<object>()); return false; } string pipeName = GetPipeName(pipe); Logger.Info("Connecting to " + pipeName + " (" + text + ")", Array.Empty<object>()); ConnectedPipe = pipe; _stream = new NamedPipeClientStream(".", pipeName); _stream.Connect(); Logger.Info("Connected", Array.Empty<object>()); return true; } catch (Exception ex) { Logger.Error("Failed: " + ex.GetType().FullName + ", " + ex.Message, Array.Empty<object>()); ConnectedPipe = -1; Close(); return false; } } public void Close() { if (_stream != null) { Logger.Trace("Closing stream", Array.Empty<object>()); ((Stream)(object)_stream).Dispose(); _stream = null; } } public void Dispose() { if (!_isDisposed) { Logger.Trace("Disposing stream", Array.Empty<object>()); _isDisposed = true; Close(); } } public bool ReadFrame(out PipeFrame frame) { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) if (_isDisposed) { throw new ObjectDisposedException("_stream"); } if (!IsConnected) { frame = default(PipeFrame); return false; } int num = ((Stream)(object)_stream).Read(_buffer, 0, _buffer.Length); Logger.Trace("Read {0} bytes", new object[1] { num }); if (num == 0) { frame = default(PipeFrame); return false; } using MemoryStream memoryStream = new MemoryStream(_buffer, 0, num); frame = default(PipeFrame); if (!((PipeFrame)(ref frame)).ReadStream((Stream)memoryStream)) { Logger.Error("Failed to read a frame! {0}", new object[1] { ((PipeFrame)(ref frame)).Opcode }); return false; } Logger.Trace("Read pipe frame!", Array.Empty<object>()); return true; } public bool WriteFrame(PipeFrame frame) { if (_isDisposed) { throw new ObjectDisposedException("_stream"); } if (!IsConnected) { Logger.Error("Failed to write frame because the stream is closed", Array.Empty<object>()); return false; } try { Logger.Trace("Writing frame", Array.Empty<object>()); ((PipeFrame)(ref frame)).WriteStream((Stream)(object)_stream); return true; } catch (IOException ex) { Logger.Error("Failed to write frame due to IOException: {0}", new object[1] { ex.Message }); } catch (ObjectDisposedException) { Logger.Warning("Failed to write frame as the stream was already disposed", Array.Empty<object>()); } catch (InvalidOperationException) { Logger.Warning("Failed to write frame because of an invalid operation", Array.Empty<object>()); } return false; } private string GetPipeName(int pipe, string sandbox = "") { switch (Environment.OSVersion.Platform) { default: Logger.Trace("PIPE WIN", Array.Empty<object>()); return sandbox + $"discord-ipc-{pipe}"; case PlatformID.Unix: case PlatformID.MacOSX: Logger.Trace("PIPE UNIX / MACOSX", Array.Empty<object>()); return Path.Combine(GetEnviromentTemp(), sandbox + $"discord-ipc-{pipe}"); } } private string GetPipeSandbox() { PlatformID platform = Environment.OSVersion.Platform; PlatformID platformID = platform; if (platformID != PlatformID.Unix) { return null; } return "snap.discord/"; } private string GetEnviromentTemp() { string text = null; text = text ?? Environment.GetEnvironmentVariable("XDG_RUNTIME_DIR"); text = text ?? Environment.GetEnvironmentVariable("TMPDIR"); text = text ?? Environment.GetEnvironmentVariable("TMP"); text = text ?? Environment.GetEnvironmentVariable("TEMP"); return text ?? "/tmp"; } } } namespace DiscordRichPresence { [BepInPlugin("com.cuno.discord", "Discord Rich Presence", "1.2.1")] [NetworkCompatibility(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public class DiscordRichPresencePlugin : BaseUnityPlugin { internal static ManualLogSource LoggerEXT { get; private set; } public static DiscordRpcClient Client { get; set; } public static RichPresence RichPresence { get; set; } public static DiscordRichPresencePlugin Instance { get; private set; } public static SceneDef CurrentScene => SceneCatalog.GetSceneDefForCurrentScene(); public static float CurrentChargeLevel { get; set; } public static float MoonCountdownTimer { get; set; } public static string CurrentBoss { get; set; } public static bool IsInEOSLobby => EOSLobbyManager.GetFromPlatformSystems() != null && ((LobbyManager)EOSLobbyManager.GetFromPlatformSystems()).isInLobby; public void Awake() { //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) //IL_0062: Unknown result type (might be due to invalid IL or missing references) //IL_006c: Expected O, but got Unknown //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Expected O, but got Unknown //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_008a: Expected O, but got Unknown Instance = this; LoggerEXT = ((BaseUnityPlugin)this).Logger; ((BaseUnityPlugin)this).Logger.LogInfo((object)"Starting Discord Rich Presence..."); UnityNamedPipe unityNamedPipe = new UnityNamedPipe(); Client = new DiscordRpcClient("992086428240580720", -1, (ILogger)null, true, (INamedPipeClient)(object)unityNamedPipe); Client.RegisterUriScheme("632360", (string)null); RichPresence = new RichPresence { State = "Starting game...", Assets = new Assets(), Secrets = new Secrets(), Timestamps = new Timestamps() }; Client.SetPresence(RichPresence); Client.Initialize(); PluginConfig.AllowJoiningEntry = ((BaseUnityPlugin)this).Config.Bind<bool>("Options", "Allow Joining", true, "Controls whether or not other users should be allowed to ask to join your game."); PluginConfig.TeleporterStatusEntry = ((BaseUnityPlugin)this).Config.Bind<PluginConfig.TeleporterStatus>("Options", "Teleporter Status", PluginConfig.TeleporterStatus.None, "Controls whether the teleporter boss, teleporter charge status, or neither, should be shown alongside the current difficulty."); PluginConfig.MainMenuIdleMessageEntry = ((BaseUnityPlugin)this).Config.Bind<string>("Options", "Main Menu Idle Message", "", "Allows you to choose a message to be displayed when idling in the main menu."); if (RiskOfOptionsUtils.IsEnabled) { RiskOfOptionsUtils.SetModDescription("Adds Discord Rich Presence functionality to Risk of Rain 2"); RiskOfOptionsUtils.AddCheckBoxOption(PluginConfig.AllowJoiningEntry); RiskOfOptionsUtils.AddMultiOption<PluginConfig.TeleporterStatus>(PluginConfig.TeleporterStatusEntry); RiskOfOptionsUtils.AddTextInputOption(PluginConfig.MainMenuIdleMessageEntry); } } private static void InitializeHooks() { DiscordClientHooks.AddHooks(Client); PauseManagerHooks.AddHooks(); SteamworksLobbyHooks.AddHooks(); RoR2Hooks.AddHooks(); SceneManager.activeSceneChanged += SceneManager_activeSceneChanged; Stage.onServerStageBegin += Stage_onServerStageBegin; } public static void Dispose() { DiscordClientHooks.RemoveHooks(Client); PauseManagerHooks.RemoveHooks(); SteamworksLobbyHooks.RemoveHooks(); RoR2Hooks.RemoveHooks(); if (((object)(UserID)(ref EOSLoginManager.loggedInUserID)).ToString() != string.Empty) { EOSLobbyHooks.RemoveHooks(); } SceneManager.activeSceneChanged -= SceneManager_activeSceneChanged; Stage.onServerStageBegin -= Stage_onServerStageBegin; Client.Dispose(); } public void OnEnable() { InitializeHooks(); } public void OnDisable() { Dispose(); } private static void SceneManager_activeSceneChanged(Scene arg0, Scene arg1) { if (Client != null && Client.IsInitialized) { CurrentBoss = ""; CurrentChargeLevel = 0f; MoonCountdownTimer = 0f; EOSLobbyManager fromPlatformSystems = EOSLobbyManager.GetFromPlatformSystems(); if (((Scene)(ref arg1)).name == "title" && Client.Instance.Lobby.IsValid) { PresenceUtils.SetLobbyPresence(Client, RichPresence, Client.Instance); } else if (((Scene)(ref arg1)).name == "title" && IsInEOSLobby) { PresenceUtils.SetLobbyPresence(Client, RichPresence, fromPlatformSystems); } if (((Scene)(ref arg1)).name == "lobby" && !Client.Instance.Lobby.IsValid && !IsInEOSLobby) { PresenceUtils.SetMainMenuPresence(Client, RichPresence, "Choosing Character"); } else if (((Scene)(ref arg1)).name == "lobby" && Client.Instance.Lobby.IsValid) { PresenceUtils.SetLobbyPresence(Client, RichPresence, Client.Instance, justParty: false, "Choosing Character"); } else if (((Scene)(ref arg1)).name == "lobby" && IsInEOSLobby) { PresenceUtils.SetLobbyPresence(Client, RichPresence, fromPlatformSystems, justParty: false, "Choosing Character"); } if (((Scene)(ref arg1)).name == "logbook") { PresenceUtils.SetMainMenuPresence(Client, RichPresence, "Reading Logbook"); } else if ((Object)(object)Run.instance != (Object)null && (Object)(object)CurrentScene != (Object)null && (Client.Instance.Lobby.IsValid || IsInEOSLobby)) { LoggerEXT.LogInfo((object)("Scene Manager Active Scene Changed Called With Value: " + (Run.instance.stageClearCount + 1))); PresenceUtils.SetStagePresence(Client, RichPresence, CurrentScene, Run.instance); } } } private static void Stage_onServerStageBegin(Stage obj) { CurrentChargeLevel = 0f; if ((Object)(object)CurrentScene != (Object)null && (Object)(object)Run.instance != (Object)null) { PresenceUtils.SetStagePresence(Client, RichPresence, CurrentScene, Run.instance); } } } public static class PluginConfig { public enum TeleporterStatus : byte { None, Boss, Charge } public static ConfigEntry<bool> AllowJoiningEntry { get; set; } public static ConfigEntry<TeleporterStatus> TeleporterStatusEntry { get; set; } public static ConfigEntry<string> MainMenuIdleMessageEntry { get; set; } } } namespace DiscordRichPresence.Utils { public static class InfoTextUtils { public enum StyleTag : byte { Damage = 1, Healing, Utility, Health, Stack, Mono, Death, UserSetting, Artifact, Sub, Event, WorldEvent, KeywordName, Shrine } public static List<string> CharactersWithAssets = new List<string> { "Acrid", "Artificer", "Bandit", "Captain", "Commando", "Engineer", "Heretic", "Huntress", "Loader", "MUL-T", "Mercenary", "REX", "Railgunner", "Enforcer", "CHEF", "Miner", "Paladin", "HAN-D", "Sniper", "Bomber", "Nemesis Enforcer", "Nemesis Commando", "Chirr", "Executioner", "An Arbiter", "Red Mist" }; public static string GetCharacterInternalName(string name) { if (name == "「V??oid Fiend』") { return "voidfiend"; } if (CharactersWithAssets.Contains(name)) { return CharactersWithAssets.Find((string c) => c == name).ToLower().Replace(" ", ""); } return "unknown"; } public static string FormatTextStyleTag(string content, StyleTag styleTag) { string text = (((int)styleTag < 1 || (int)styleTag > 4) ? ("c" + styleTag) : ("cIs" + styleTag)); return "<style=" + text + ">" + content + "</style>"; } } public static class PresenceUtils { public static void SetStagePresence(DiscordRpcClient client, RichPresence richPresence, SceneDef scene, Run run, bool isPaused = false) { //IL_00f6: Unknown result type (might be due to invalid IL or missing references) //IL_010c: Unknown result type (might be due to invalid IL or missing references) //IL_0116: Expected O, but got Unknown //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0122: Expected O, but got Unknown //IL_028d: Unknown result type (might be due to invalid IL or missing references) //IL_0293: Invalid comparison between Unknown and I4 if ((Object)(object)Run.instance == (Object)null) { DiscordRichPresencePlugin.LoggerEXT.LogError((object)"Run instance is null. Check for its null status before passing it as a parameter. Stack trace follows:"); } if ((Object)(object)scene == (Object)null) { DiscordRichPresencePlugin.LoggerEXT.LogError((object)"Scene is null. Check for its null status before passing it as a parameter. Stack trace follows:"); } ((BaseRichPresence)richPresence).Assets.LargeImageKey = scene.baseSceneName; ((BaseRichPresence)richPresence).Assets.LargeImageText = "DiscordRichPresence v" + ((BaseUnityPlugin)DiscordRichPresencePlugin.Instance).Info.Metadata.Version; ((BaseRichPresence)richPresence).State = $"Stage {run.stageClearCount + 1} - {Language.GetString(scene.nameToken)}"; InfiniteTowerRun val = (InfiniteTowerRun)(object)((run is InfiniteTowerRun) ? run : null); if (val != null && val.waveIndex > 0) { ((BaseRichPresence)richPresence).State = $"Wave {val.waveIndex} - {Language.GetString(scene.nameToken)}"; } string @string = Language.GetString(DifficultyCatalog.GetDifficultyDef(run.selectedDifficulty).nameToken); ((BaseRichPresence)richPresence).Timestamps = new Timestamps(); ((BaseRichPresence)richPresence).Secrets = new Secrets(); if (scene.baseSceneName == "outro") { DiscordRichPresencePlugin.MoonCountdownTimer = 0f; ((BaseRichPresence)richPresence).Assets.LargeImageKey = "moon2"; ((BaseRichPresence)richPresence).Details = "Credits"; ((BaseRichPresence)richPresence).State = $"Stage {run.stageClearCount + 1} - {Language.GetString(scene.nameToken)}"; } else if (DiscordRichPresencePlugin.MoonCountdownTimer > 0f) { ((BaseRichPresence)richPresence).Details = "Escaping! | " + @string; if (!isPaused) { ((BaseRichPresence)richPresence).Timestamps.EndUnixMilliseconds = (ulong)DateTimeOffset.Now.ToUnixTimeSeconds() + (ulong)DiscordRichPresencePlugin.MoonCountdownTimer; } } else { ((BaseRichPresence)richPresence).Details = @string; if (PluginConfig.TeleporterStatusEntry.Value == PluginConfig.TeleporterStatus.Boss && DiscordRichPresencePlugin.CurrentBoss != "") { ((BaseRichPresence)richPresence).Details = "Fighting " + DiscordRichPresencePlugin.CurrentBoss + " | " + @string; } else if (PluginConfig.TeleporterStatusEntry.Value == PluginConfig.TeleporterStatus.Charge && DiscordRichPresencePlugin.CurrentChargeLevel > 0f) { ((BaseRichPresence)richPresence).Details = "Charging teleporter (" + DiscordRichPresencePlugin.CurrentChargeLevel * 100f + "%) | " + @string; } if ((int)scene.sceneType == 1 && !isPaused) { ((BaseRichPresence)richPresence).Timestamps.StartUnixMilliseconds = (ulong)DateTimeOffset.Now.ToUnixTimeSeconds() - (ulong)run.GetRunStopwatch(); } } DiscordRichPresencePlugin.RichPresence = richPresence; client.SetPresence(richPresence); } public static void SetMainMenuPresence(DiscordRpcClient client, RichPresence richPresence, string details = "") { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Expected O, but got Unknown //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown ((BaseRichPresence)richPresence).Assets = new Assets { LargeImageKey = "riskofrain2", LargeImageText = "DiscordRichPresence v" + ((BaseUnityPlugin)DiscordRichPresencePlugin.Instance).Info.Metadata.Version }; ((BaseRichPresence)richPresence).Details = PluginConfig.MainMenuIdleMessageEntry.Value; if (details != "") { ((BaseRichPresence)richPresence).Details = details; } ((BaseRichPresence)richPresence).Timestamps = new Timestamps(); ((BaseRichPresence)richPresence).State = "In Menu"; ((BaseRichPresence)richPresence).Secrets = new Secrets(); ((BaseRichPresence)richPresence).Party = new Party(); DiscordRichPresencePlugin.RichPresence = richPresence; client.SetPresence(richPresence); } public static void SetLobbyPresence(DiscordRpcClient client, RichPresence richPresence, Client faceClient, bool justParty = false, string details = "") { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown if (!justParty) { ((BaseRichPresence)richPresence).State = "In Lobby"; ((BaseRichPresence)richPresence).Details = "Preparing"; if (details != "") { ((BaseRichPresence)richPresence).Details = details; } ((BaseRichPresence)richPresence).Assets = new Assets { LargeImageKey = "riskofrain2", LargeImageText = "DiscordRichPresence v" + ((BaseUnityPlugin)DiscordRichPresencePlugin.Instance).Info.Metadata.Version }; ((BaseRichPresence)richPresence).Timestamps = new Timestamps(); } richPresence = UpdateParty(richPresence, faceClient); DiscordRichPresencePlugin.RichPresence = richPresence; client.SetPresence(richPresence); } public static void SetLobbyPresence(DiscordRpcClient client, RichPresence richPresence, EOSLobbyManager lobbyManager, bool justParty = false, string details = "") { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0087: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown if (!justParty) { ((BaseRichPresence)richPresence).State = "In Lobby"; ((BaseRichPresence)richPresence).Details = "Preparing"; if (details != "") { ((BaseRichPresence)richPresence).Details = details; } ((BaseRichPresence)richPresence).Assets = new Assets { LargeImageKey = "riskofrain2", LargeImageText = "DiscordRichPresence v" + ((BaseUnityPlugin)DiscordRichPresencePlugin.Instance).Info.Metadata.Version }; ((BaseRichPresence)richPresence).Timestamps = new Timestamps(); } richPresence = UpdateParty(richPresence, lobbyManager); DiscordRichPresencePlugin.RichPresence = richPresence; client.SetPresence(richPresence); } public static RichPresence UpdateParty(RichPresence richPresence, Client faceClient, bool includeJoinButton = true) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown ((BaseRichPresence)richPresence).Party.ID = faceClient.Username; ((BaseRichPresence)richPresence).Party.Max = faceClient.Lobby.MaxMembers; ((BaseRichPresence)richPresence).Party.Size = faceClient.Lobby.NumMembers; ((BaseRichPresence)richPresence).Secrets = new Secrets(); if (PluginConfig.AllowJoiningEntry.Value && includeJoinButton) { ((BaseRichPresence)richPresence).Secrets.JoinSecret = faceClient.Lobby.CurrentLobby.ToString(); } return richPresence; } public static RichPresence UpdateParty(RichPresence richPresence, EOSLobbyManager lobbyManager, bool includeJoinButton = true) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown ((BaseRichPresence)richPresence).Party.ID = lobbyManager.CurrentLobbyId; ((BaseRichPresence)richPresence).Party.Max = ((LobbyManager)lobbyManager).newestLobbyData.totalMaxPlayers; ((BaseRichPresence)richPresence).Party.Size = ((LobbyManager)lobbyManager).newestLobbyData.totalPlayerCount; ((BaseRichPresence)richPresence).Secrets = new Secrets(); if (PluginConfig.AllowJoiningEntry.Value && includeJoinButton) { ((BaseRichPresence)richPresence).Secrets.JoinSecret = ((object)(UserID)(ref ((LobbyManager)lobbyManager).GetLobbyMembers()[0])).ToString(); } return richPresence; } } public static class RiskOfOptionsUtils { public static bool IsEnabled => Chainloader.PluginInfos.ContainsKey("com.rune580.riskofoptions"); public static void AddCheckBoxOption(ConfigEntry<bool> entry) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new CheckBoxOption(entry)); } public static void AddMultiOption<T>(ConfigEntry<T> entry) where T : Enum { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new ChoiceOption((ConfigEntryBase)(object)entry)); } public static void AddTextInputOption(ConfigEntry<string> entry) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Expected O, but got Unknown ModSettingsManager.AddOption((BaseOption)new StringInputFieldOption(entry)); } public static void SetModDescription(string description) { ModSettingsManager.SetModDescription(description); } } } namespace DiscordRichPresence.Hooks { public static class DiscordClientHooks { [CompilerGenerated] private static class <>O { public static OnReadyEvent <0>__Client_OnReady; public static OnErrorEvent <1>__Client_OnError; public static OnJoinRequestedEvent <2>__Client_OnJoinRequested; public static OnJoinEvent <3>__Client_OnJoin; } public static void AddHooks(DiscordRpcClient client) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown client.Subscribe((EventType)2); client.Subscribe((EventType)4); object obj = <>O.<0>__Client_OnReady; if (obj == null) { OnReadyEvent val = Client_OnReady; <>O.<0>__Client_OnReady = val; obj = (object)val; } client.OnReady += (OnReadyEvent)obj; object obj2 = <>O.<1>__Client_OnError; if (obj2 == null) { OnErrorEvent val2 = Client_OnError; <>O.<1>__Client_OnError = val2; obj2 = (object)val2; } client.OnError += (OnErrorEvent)obj2; object obj3 = <>O.<2>__Client_OnJoinRequested; if (obj3 == null) { OnJoinRequestedEvent val3 = Client_OnJoinRequested; <>O.<2>__Client_OnJoinRequested = val3; obj3 = (object)val3; } client.OnJoinRequested += (OnJoinRequestedEvent)obj3; object obj4 = <>O.<3>__Client_OnJoin; if (obj4 == null) { OnJoinEvent val4 = Client_OnJoin; <>O.<3>__Client_OnJoin = val4; obj4 = (object)val4; } client.OnJoin += (OnJoinEvent)obj4; } public static void RemoveHooks(DiscordRpcClient client) { //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Expected O, but got Unknown //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_0088: Unknown result type (might be due to invalid IL or missing references) //IL_008d: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown client.Unsubscribe((EventType)2); client.Unsubscribe((EventType)4); object obj = <>O.<0>__Client_OnReady; if (obj == null) { OnReadyEvent val = Client_OnReady; <>O.<0>__Client_OnReady = val; obj = (object)val; } client.OnReady -= (OnReadyEvent)obj; object obj2 = <>O.<1>__Client_OnError; if (obj2 == null) { OnErrorEvent val2 = Client_OnError; <>O.<1>__Client_OnError = val2; obj2 = (object)val2; } client.OnError -= (OnErrorEvent)obj2; object obj3 = <>O.<2>__Client_OnJoinRequested; if (obj3 == null) { OnJoinRequestedEvent val3 = Client_OnJoinRequested; <>O.<2>__Client_OnJoinRequested = val3; obj3 = (object)val3; } client.OnJoinRequested -= (OnJoinRequestedEvent)obj3; object obj4 = <>O.<3>__Client_OnJoin; if (obj4 == null) { OnJoinEvent val4 = Client_OnJoin; <>O.<3>__Client_OnJoin = val4; obj4 = (object)val4; } client.OnJoin -= (OnJoinEvent)obj4; } private static void Client_OnReady(object sender, ReadyMessage args) { //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0048: Unknown result type (might be due to invalid IL or missing references) //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_00a2: Expected O, but got Unknown //IL_00a3: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Unknown result type (might be due to invalid IL or missing references) //IL_00ae: Expected O, but got Unknown //IL_00b4: Expected O, but got Unknown DiscordRichPresencePlugin.LoggerEXT.LogInfo((object)("Discord Rich Presence Ready - User: " + args.User.Username)); if (DiscordRichPresencePlugin.Client != null && DiscordRichPresencePlugin.Client.IsInitialized) { DiscordRichPresencePlugin.RichPresence = new RichPresence { Assets = new Assets { LargeImageKey = "riskofrain2", LargeImageText = "DiscordRichPresence v" + ((BaseUnityPlugin)DiscordRichPresencePlugin.Instance).Info.Metadata.Version }, State = "Starting game...", Secrets = new Secrets(), Timestamps = new Timestamps() }; DiscordRichPresencePlugin.Client.SetPresence(DiscordRichPresencePlugin.RichPresence); } } private static void Client_OnError(object sender, ErrorMessage args) { DiscordRichPresencePlugin.LoggerEXT.LogError((object)args.Message); DiscordRichPresencePlugin.Dispose(); } private static void Client_OnJoinRequested(object sender, JoinRequestMessage args) { //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Expected O, but got Unknown DiscordRichPresencePlugin.LoggerEXT.LogInfo((object)$"User {args.User.Username} asked to join lobby"); Chat.AddMessage($"Discord user {InfoTextUtils.FormatTextStyleTag(args.User.Username, InfoTextUtils.StyleTag.Event)} has asked to join your game!"); DiscordRpcClient val = (DiscordRpcClient)sender; val.Respond(args, true); } private static void Client_OnJoin(object sender, JoinMessage args) { //IL_0091: Unknown result type (might be due to invalid IL or missing references) //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0051: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) if (Client.Instance.Lobby.IsValid) { DiscordRichPresencePlugin.LoggerEXT.LogInfo((object)("Joining Game via Discord - Steam Lobby ID: " + args.Secret)); ConCommandArgs val = default(ConCommandArgs); val.userArgs = new List<string> { args.Secret }; ConCommandArgs val2 = val; ((PCLobbyManager)SteamworksLobbyManager.GetFromPlatformSystems()).JoinLobby(val2); } else { DiscordRichPresencePlugin.LoggerEXT.LogInfo((object)("Joining Game via Discord - EOS User ID: " + args.Secret)); UserID val3 = default(UserID); UserID.TryParse(args.Secret, ref val3); ((LobbyManager)EOSLobbyManager.GetFromPlatformSystems()).JoinLobby(val3); } } } public static class EOSLobbyHooks { [CompilerGenerated] private static class <>O { public static hook_OnLobbyCreated <0>__EOSLobbyManager_OnLobbyCreated; public static hook_OnLobbyJoined <1>__EOSLobbyManager_OnLobbyJoined; public static hook_OnLobbyChanged <2>__EOSLobbyManager_OnLobbyChanged; public static hook_LeaveLobby <3>__EOSLobbyManager_LeaveLobby; } public static void AddHooks() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown try { object obj = <>O.<0>__EOSLobbyManager_OnLobbyCreated; if (obj == null) { hook_OnLobbyCreated val = EOSLobbyManager_OnLobbyCreated; <>O.<0>__EOSLobbyManager_OnLobbyCreated = val; obj = (object)val; } EOSLobbyManager.OnLobbyCreated += (hook_OnLobbyCreated)obj; object obj2 = <>O.<1>__EOSLobbyManager_OnLobbyJoined; if (obj2 == null) { hook_OnLobbyJoined val2 = EOSLobbyManager_OnLobbyJoined; <>O.<1>__EOSLobbyManager_OnLobbyJoined = val2; obj2 = (object)val2; } EOSLobbyManager.OnLobbyJoined += (hook_OnLobbyJoined)obj2; object obj3 = <>O.<2>__EOSLobbyManager_OnLobbyChanged; if (obj3 == null) { hook_OnLobbyChanged val3 = EOSLobbyManager_OnLobbyChanged; <>O.<2>__EOSLobbyManager_OnLobbyChanged = val3; obj3 = (object)val3; } EOSLobbyManager.OnLobbyChanged += (hook_OnLobbyChanged)obj3; object obj4 = <>O.<3>__EOSLobbyManager_LeaveLobby; if (obj4 == null) { hook_LeaveLobby val4 = EOSLobbyManager_LeaveLobby; <>O.<3>__EOSLobbyManager_LeaveLobby = val4; obj4 = (object)val4; } EOSLobbyManager.LeaveLobby += (hook_LeaveLobby)obj4; } catch (BadImageFormatException) { DiscordRichPresencePlugin.LoggerEXT.LogError((object)"Couldn't hook EOS methods"); } } public static void RemoveHooks() { //IL_0012: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Expected O, but got Unknown //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003e: Expected O, but got Unknown //IL_0054: Unknown result type (might be due to invalid IL or missing references) //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Expected O, but got Unknown try { object obj = <>O.<0>__EOSLobbyManager_OnLobbyCreated; if (obj == null) { hook_OnLobbyCreated val = EOSLobbyManager_OnLobbyCreated; <>O.<0>__EOSLobbyManager_OnLobbyCreated = val; obj = (object)val; } EOSLobbyManager.OnLobbyCreated -= (hook_OnLobbyCreated)obj; object obj2 = <>O.<1>__EOSLobbyManager_OnLobbyJoined; if (obj2 == null) { hook_OnLobbyJoined val2 = EOSLobbyManager_OnLobbyJoined; <>O.<1>__EOSLobbyManager_OnLobbyJoined = val2; obj2 = (object)val2; } EOSLobbyManager.OnLobbyJoined -= (hook_OnLobbyJoined)obj2; object obj3 = <>O.<2>__EOSLobbyManager_OnLobbyChanged; if (obj3 == null) { hook_OnLobbyChanged val3 = EOSLobbyManager_OnLobbyChanged; <>O.<2>__EOSLobbyManager_OnLobbyChanged = val3; obj3 = (object)val3; } EOSLobbyManager.OnLobbyChanged -= (hook_OnLobbyChanged)obj3; object obj4 = <>O.<3>__EOSLobbyManager_LeaveLobby; if (obj4 == null) { hook_LeaveLobby val4 = EOSLobbyManager_LeaveLobby; <>O.<3>__EOSLobbyManager_LeaveLobby = val4; obj4 = (object)val4; } EOSLobbyManager.LeaveLobby -= (hook_LeaveLobby)obj4; } catch (BadImageFormatException) { DiscordRichPresencePlugin.LoggerEXT.LogError((object)"Couldn't unhook EOS methods"); } } private static void EOSLobbyManager_OnLobbyCreated(orig_OnLobbyCreated orig, EOSLobbyManager self, CreateLobbyCallbackInfo data) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) orig.Invoke(self, data); if ((int)data.ResultCode == 0 && self != null) { DiscordRichPresencePlugin.LoggerEXT.LogInfo((object)("Discord broadcasting new EOS lobby with ID " + self.CurrentLobbyId)); PresenceUtils.SetLobbyPresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence, self); } } private static void EOSLobbyManager_OnLobbyJoined(orig_OnLobbyJoined orig, EOSLobbyManager self, JoinLobbyCallbackInfo data) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) orig.Invoke(self, data); if ((int)data.ResultCode == 0 && self != null) { DiscordRichPresencePlugin.LoggerEXT.LogInfo((object)"Successfully joined EOS lobby"); PresenceUtils.SetLobbyPresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence, self); } } private static void EOSLobbyManager_OnLobbyChanged(orig_OnLobbyChanged orig, EOSLobbyManager self) { orig.Invoke(self); if (self != null && ((LobbyManager)self).isInLobby) { DiscordRichPresencePlugin.LoggerEXT.LogInfo((object)"Discord re-broadcasting EOS lobby"); if ((Object)(object)Run.instance == (Object)null) { PresenceUtils.SetLobbyPresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence, self, ((BaseRichPresence)DiscordRichPresencePlugin.RichPresence).Details == "Choosing Character"); return; } DiscordRichPresencePlugin.RichPresence = PresenceUtils.UpdateParty(DiscordRichPresencePlugin.RichPresence, self, includeJoinButton: false); PresenceUtils.SetStagePresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence, DiscordRichPresencePlugin.CurrentScene, Run.instance); } } private static void EOSLobbyManager_LeaveLobby(orig_LeaveLobby orig, EOSLobbyManager self) { orig.Invoke(self); if (DiscordRichPresencePlugin.Client != null && DiscordRichPresencePlugin.Client.IsInitialized) { PresenceUtils.SetMainMenuPresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence); } } public static void EOSLoginManager_CompleteConnectLogin(orig_CompleteConnectLogin orig, EOSLoginManager self, ProductUserId localUserId) { orig.Invoke(self, localUserId); AddHooks(); DiscordRichPresencePlugin.LoggerEXT.LogInfo((object)((object)(UserID)(ref EOSLoginManager.loggedInUserID)).ToString()); } } public static class PauseManagerHooks { public static void AddHooks() { PauseManager.onPauseStartGlobal = (Action)Delegate.Combine(PauseManager.onPauseStartGlobal, new Action(OnGamePaused)); PauseManager.onPauseEndGlobal = (Action)Delegate.Combine(PauseManager.onPauseEndGlobal, new Action(OnGameUnPaused)); } public static void RemoveHooks() { PauseManager.onPauseStartGlobal = (Action)Delegate.Remove(PauseManager.onPauseStartGlobal, new Action(OnGamePaused)); PauseManager.onPauseEndGlobal = (Action)Delegate.Remove(PauseManager.onPauseEndGlobal, new Action(OnGameUnPaused)); } private static void OnGamePaused() { if ((Object)(object)Run.instance != (Object)null && (Object)(object)DiscordRichPresencePlugin.CurrentScene != (Object)null) { PresenceUtils.SetStagePresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence, DiscordRichPresencePlugin.CurrentScene, Run.instance, isPaused: true); } } private static void OnGameUnPaused() { if ((Object)(object)Run.instance != (Object)null && (Object)(object)DiscordRichPresencePlugin.CurrentScene != (Object)null) { PresenceUtils.SetStagePresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence, DiscordRichPresencePlugin.CurrentScene, Run.instance); } } } public static class RoR2Hooks { [CompilerGenerated] private static class <>O { public static Action<CharacterBody> <0>__CharacterBody_onBodyStartGlobal; public static Action<CharacterBody> <1>__CharacterBody_onBodyDestroyGlobal; public static hook_Start <2>__Stage_Start; public static hook_FixedUpdate <3>__TeleporterInteraction_FixedUpdate; public static hook_SetCountdownTime <4>__EscapeSequenceController_SetCountdownTime; public static hook_BeginNextWave <5>__InfiniteTowerRun_BeginNextWave; public static hook_OnEnter <6>__BaseMainMenuScreen_OnEnter; } public static void AddHooks() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown CharacterBody.onBodyStartGlobal += CharacterBody_onBodyStartGlobal; CharacterBody.onBodyDestroyGlobal += CharacterBody_onBodyDestroyGlobal; object obj = <>O.<2>__Stage_Start; if (obj == null) { hook_Start val = Stage_Start; <>O.<2>__Stage_Start = val; obj = (object)val; } Stage.Start += (hook_Start)obj; object obj2 = <>O.<3>__TeleporterInteraction_FixedUpdate; if (obj2 == null) { hook_FixedUpdate val2 = TeleporterInteraction_FixedUpdate; <>O.<3>__TeleporterInteraction_FixedUpdate = val2; obj2 = (object)val2; } TeleporterInteraction.FixedUpdate += (hook_FixedUpdate)obj2; object obj3 = <>O.<4>__EscapeSequenceController_SetCountdownTime; if (obj3 == null) { hook_SetCountdownTime val3 = EscapeSequenceController_SetCountdownTime; <>O.<4>__EscapeSequenceController_SetCountdownTime = val3; obj3 = (object)val3; } EscapeSequenceController.SetCountdownTime += (hook_SetCountdownTime)obj3; object obj4 = <>O.<5>__InfiniteTowerRun_BeginNextWave; if (obj4 == null) { hook_BeginNextWave val4 = InfiniteTowerRun_BeginNextWave; <>O.<5>__InfiniteTowerRun_BeginNextWave = val4; obj4 = (object)val4; } InfiniteTowerRun.BeginNextWave += (hook_BeginNextWave)obj4; object obj5 = <>O.<6>__BaseMainMenuScreen_OnEnter; if (obj5 == null) { hook_OnEnter val5 = BaseMainMenuScreen_OnEnter; <>O.<6>__BaseMainMenuScreen_OnEnter = val5; obj5 = (object)val5; } BaseMainMenuScreen.OnEnter += (hook_OnEnter)obj5; } private static void Stage_Start(orig_Start orig, Stage self) { orig.Invoke(self); LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser(); object obj; if (firstLocalUser == null) { obj = null; } else { PlayerCharacterMasterController cachedMasterController = firstLocalUser.cachedMasterController; if (cachedMasterController == null) { obj = null; } else { CharacterMaster master = cachedMasterController.master; obj = ((master != null) ? master.GetBody() : null); } } CharacterBody val = (CharacterBody)obj; if (!((Object)(object)val == (Object)null)) { DiscordRichPresencePlugin.LoggerEXT.LogInfo((object)("LocalBodyBaseName: " + val.baseNameToken)); ((BaseRichPresence)DiscordRichPresencePlugin.RichPresence).Assets.SmallImageKey = InfoTextUtils.GetCharacterInternalName(val.GetDisplayName()); ((BaseRichPresence)DiscordRichPresencePlugin.RichPresence).Assets.SmallImageText = val.GetDisplayName(); DiscordRichPresencePlugin.Client.SetPresence(DiscordRichPresencePlugin.RichPresence); PresenceUtils.SetStagePresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence, DiscordRichPresencePlugin.CurrentScene, Run.instance); } } public static void RemoveHooks() { //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_009a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c1: Expected O, but got Unknown //IL_00d7: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Expected O, but got Unknown CharacterBody.onBodyStartGlobal -= CharacterBody_onBodyStartGlobal; CharacterBody.onBodyDestroyGlobal -= CharacterBody_onBodyDestroyGlobal; object obj = <>O.<2>__Stage_Start; if (obj == null) { hook_Start val = Stage_Start; <>O.<2>__Stage_Start = val; obj = (object)val; } Stage.Start -= (hook_Start)obj; object obj2 = <>O.<3>__TeleporterInteraction_FixedUpdate; if (obj2 == null) { hook_FixedUpdate val2 = TeleporterInteraction_FixedUpdate; <>O.<3>__TeleporterInteraction_FixedUpdate = val2; obj2 = (object)val2; } TeleporterInteraction.FixedUpdate -= (hook_FixedUpdate)obj2; object obj3 = <>O.<4>__EscapeSequenceController_SetCountdownTime; if (obj3 == null) { hook_SetCountdownTime val3 = EscapeSequenceController_SetCountdownTime; <>O.<4>__EscapeSequenceController_SetCountdownTime = val3; obj3 = (object)val3; } EscapeSequenceController.SetCountdownTime -= (hook_SetCountdownTime)obj3; object obj4 = <>O.<5>__InfiniteTowerRun_BeginNextWave; if (obj4 == null) { hook_BeginNextWave val4 = InfiniteTowerRun_BeginNextWave; <>O.<5>__InfiniteTowerRun_BeginNextWave = val4; obj4 = (object)val4; } InfiniteTowerRun.BeginNextWave -= (hook_BeginNextWave)obj4; object obj5 = <>O.<6>__BaseMainMenuScreen_OnEnter; if (obj5 == null) { hook_OnEnter val5 = BaseMainMenuScreen_OnEnter; <>O.<6>__BaseMainMenuScreen_OnEnter = val5; obj5 = (object)val5; } BaseMainMenuScreen.OnEnter -= (hook_OnEnter)obj5; } private static void CharacterBody_onBodyStartGlobal(CharacterBody obj) { if (obj.isChampion) { DiscordRichPresencePlugin.CurrentBoss = obj.GetDisplayName(); PresenceUtils.SetStagePresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence, DiscordRichPresencePlugin.CurrentScene, Run.instance); } } private static void CharacterBody_onBodyDestroyGlobal(CharacterBody obj) { if (obj.isChampion && (Object)(object)Run.instance != (Object)null) { DiscordRichPresencePlugin.CurrentBoss = ""; PresenceUtils.SetStagePresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence, DiscordRichPresencePlugin.CurrentScene, Run.instance); } } private static void TeleporterInteraction_FixedUpdate(orig_FixedUpdate orig, TeleporterInteraction self) { if (Math.Round(self.chargeFraction, 2) != (double)DiscordRichPresencePlugin.CurrentChargeLevel && PluginConfig.TeleporterStatusEntry.Value == PluginConfig.TeleporterStatus.Charge) { DiscordRichPresencePlugin.CurrentChargeLevel = (float)Math.Round(self.chargeFraction, 2); PresenceUtils.SetStagePresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence, DiscordRichPresencePlugin.CurrentScene, Run.instance); } orig.Invoke(self); } private static void EscapeSequenceController_SetCountdownTime(orig_SetCountdownTime orig, EscapeSequenceController self, double secondsRemaining) { DiscordRichPresencePlugin.MoonCountdownTimer = (float)secondsRemaining + 1f; PresenceUtils.SetStagePresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence, DiscordRichPresencePlugin.CurrentScene, Run.instance); orig.Invoke(self, secondsRemaining); } private static void InfiniteTowerRun_BeginNextWave(orig_BeginNextWave orig, InfiniteTowerRun self) { PresenceUtils.SetStagePresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence, DiscordRichPresencePlugin.CurrentScene, (Run)(object)self); orig.Invoke(self); } private static void BaseMainMenuScreen_OnEnter(orig_OnEnter orig, BaseMainMenuScreen self, MainMenuController mainMenuController) { if (Client.Instance.Lobby.IsValid) { PresenceUtils.SetLobbyPresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence, Client.Instance); } else if (DiscordRichPresencePlugin.IsInEOSLobby) { PresenceUtils.SetLobbyPresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence, EOSLobbyManager.GetFromPlatformSystems()); } else { PresenceUtils.SetMainMenuPresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence); } orig.Invoke(self, mainMenuController); } } public static class SteamworksLobbyHooks { [CompilerGenerated] private static class <>O { public static hook_OnLobbyCreated <0>__SteamworksLobbyManager_OnLobbyCreated; public static hook_OnLobbyJoined <1>__SteamworksLobbyManager_OnLobbyJoined; public static hook_OnLobbyChanged <2>__SteamworksLobbyManager_OnLobbyChanged; public static hook_LeaveLobby <3>__SteamworksLobbyManager_LeaveLobby; } public static void AddHooks() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown object obj = <>O.<0>__SteamworksLobbyManager_OnLobbyCreated; if (obj == null) { hook_OnLobbyCreated val = SteamworksLobbyManager_OnLobbyCreated; <>O.<0>__SteamworksLobbyManager_OnLobbyCreated = val; obj = (object)val; } SteamworksLobbyManager.OnLobbyCreated += (hook_OnLobbyCreated)obj; object obj2 = <>O.<1>__SteamworksLobbyManager_OnLobbyJoined; if (obj2 == null) { hook_OnLobbyJoined val2 = SteamworksLobbyManager_OnLobbyJoined; <>O.<1>__SteamworksLobbyManager_OnLobbyJoined = val2; obj2 = (object)val2; } SteamworksLobbyManager.OnLobbyJoined += (hook_OnLobbyJoined)obj2; object obj3 = <>O.<2>__SteamworksLobbyManager_OnLobbyChanged; if (obj3 == null) { hook_OnLobbyChanged val3 = SteamworksLobbyManager_OnLobbyChanged; <>O.<2>__SteamworksLobbyManager_OnLobbyChanged = val3; obj3 = (object)val3; } SteamworksLobbyManager.OnLobbyChanged += (hook_OnLobbyChanged)obj3; object obj4 = <>O.<3>__SteamworksLobbyManager_LeaveLobby; if (obj4 == null) { hook_LeaveLobby val4 = SteamworksLobbyManager_LeaveLobby; <>O.<3>__SteamworksLobbyManager_LeaveLobby = val4; obj4 = (object)val4; } SteamworksLobbyManager.LeaveLobby += (hook_LeaveLobby)obj4; } public static void RemoveHooks() { //IL_0011: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Expected O, but got Unknown //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Expected O, but got Unknown //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005e: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_0079: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown object obj = <>O.<0>__SteamworksLobbyManager_OnLobbyCreated; if (obj == null) { hook_OnLobbyCreated val = SteamworksLobbyManager_OnLobbyCreated; <>O.<0>__SteamworksLobbyManager_OnLobbyCreated = val; obj = (object)val; } SteamworksLobbyManager.OnLobbyCreated -= (hook_OnLobbyCreated)obj; object obj2 = <>O.<1>__SteamworksLobbyManager_OnLobbyJoined; if (obj2 == null) { hook_OnLobbyJoined val2 = SteamworksLobbyManager_OnLobbyJoined; <>O.<1>__SteamworksLobbyManager_OnLobbyJoined = val2; obj2 = (object)val2; } SteamworksLobbyManager.OnLobbyJoined -= (hook_OnLobbyJoined)obj2; object obj3 = <>O.<2>__SteamworksLobbyManager_OnLobbyChanged; if (obj3 == null) { hook_OnLobbyChanged val3 = SteamworksLobbyManager_OnLobbyChanged; <>O.<2>__SteamworksLobbyManager_OnLobbyChanged = val3; obj3 = (object)val3; } SteamworksLobbyManager.OnLobbyChanged -= (hook_OnLobbyChanged)obj3; object obj4 = <>O.<3>__SteamworksLobbyManager_LeaveLobby; if (obj4 == null) { hook_LeaveLobby val4 = SteamworksLobbyManager_LeaveLobby; <>O.<3>__SteamworksLobbyManager_LeaveLobby = val4; obj4 = (object)val4; } SteamworksLobbyManager.LeaveLobby -= (hook_LeaveLobby)obj4; } private static void SteamworksLobbyManager_OnLobbyCreated(orig_OnLobbyCreated orig, SteamworksLobbyManager self, bool success) { orig.Invoke(self, success); if (success && Client.Instance != null) { DiscordRichPresencePlugin.LoggerEXT.LogInfo((object)("Discord broadcasting new Steam lobby with ID " + Client.Instance.Lobby.CurrentLobby)); PresenceUtils.SetLobbyPresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence, Client.Instance); } } private static void SteamworksLobbyManager_OnLobbyJoined(orig_OnLobbyJoined orig, SteamworksLobbyManager self, bool success) { orig.Invoke(self, success); if (success && Client.Instance != null) { DiscordRichPresencePlugin.LoggerEXT.LogInfo((object)"Successfully joined Steam lobby"); PresenceUtils.SetLobbyPresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence, Client.Instance); } } private static void SteamworksLobbyManager_OnLobbyChanged(orig_OnLobbyChanged orig, SteamworksLobbyManager self) { orig.Invoke(self); if (((LobbyManager)self).isInLobby && Client.Instance != null) { DiscordRichPresencePlugin.LoggerEXT.LogInfo((object)"Discord re-broadcasting Steam lobby"); if ((Object)(object)Run.instance == (Object)null) { PresenceUtils.SetLobbyPresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence, Client.Instance, ((BaseRichPresence)DiscordRichPresencePlugin.RichPresence).Details == "Choosing Character"); return; } DiscordRichPresencePlugin.RichPresence = PresenceUtils.UpdateParty(DiscordRichPresencePlugin.RichPresence, Client.Instance, includeJoinButton: false); PresenceUtils.SetStagePresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence, DiscordRichPresencePlugin.CurrentScene, Run.instance); } } private static void SteamworksLobbyManager_LeaveLobby(orig_LeaveLobby orig, SteamworksLobbyManager self) { orig.Invoke(self); if (DiscordRichPresencePlugin.Client != null && DiscordRichPresencePlugin.Client.IsInitialized) { PresenceUtils.SetMainMenuPresence(DiscordRichPresencePlugin.Client, DiscordRichPresencePlugin.RichPresence); } } } }
Cuno-DiscordRichPresence-1.2.1/DiscordRPC.dll
Decompiled 2 months agousing System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.IO.Pipes; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using System.Threading; using DiscordRPC.Converters; using DiscordRPC.Events; using DiscordRPC.Exceptions; using DiscordRPC.Helper; using DiscordRPC.IO; using DiscordRPC.Logging; using DiscordRPC.Message; using DiscordRPC.RPC; using DiscordRPC.RPC.Commands; using DiscordRPC.RPC.Payload; using DiscordRPC.Registry; using Microsoft.Win32; using Newtonsoft.Json; using Newtonsoft.Json.Linq; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: AssemblyTitle("Discord RPC")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("Discord RPC")] [assembly: AssemblyCopyright("Copyright © 2021")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("819d20d6-8d88-45c1-a4d2-aa21f10abd19")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyVersion("1.0.0.0")] namespace DiscordRPC { public class Configuration { [JsonProperty("api_endpoint")] public string ApiEndpoint { get; set; } [JsonProperty("cdn_host")] public string CdnHost { get; set; } [JsonProperty("enviroment")] public string Enviroment { get; set; } } public sealed class DiscordRpcClient : IDisposable { private ILogger _logger; private RpcConnection connection; private bool _shutdownOnly = true; private object _sync = new object(); public bool HasRegisteredUriScheme { get; private set; } public string ApplicationID { get; private set; } public string SteamID { get; private set; } public int ProcessID { get; private set; } public int MaxQueueSize { get; private set; } public bool IsDisposed { get; private set; } public ILogger Logger { get { return _logger; } set { _logger = value; if (connection != null) { connection.Logger = value; } } } public bool AutoEvents { get; private set; } public bool SkipIdenticalPresence { get; set; } public int TargetPipe { get; private set; } public RichPresence CurrentPresence { get; private set; } public EventType Subscription { get; private set; } public User CurrentUser { get; private set; } public Configuration Configuration { get; private set; } public bool IsInitialized { get; private set; } public bool ShutdownOnly { get { return _shutdownOnly; } set { _shutdownOnly = value; if (connection != null) { connection.ShutdownOnly = value; } } } public event OnReadyEvent OnReady; public event OnCloseEvent OnClose; public event OnErrorEvent OnError; public event OnPresenceUpdateEvent OnPresenceUpdate; public event OnSubscribeEvent OnSubscribe; public event OnUnsubscribeEvent OnUnsubscribe; public event OnJoinEvent OnJoin; public event OnSpectateEvent OnSpectate; public event OnJoinRequestedEvent OnJoinRequested; public event OnConnectionEstablishedEvent OnConnectionEstablished; public event OnConnectionFailedEvent OnConnectionFailed; public event OnRpcMessageEvent OnRpcMessage; public DiscordRpcClient(string applicationID) : this(applicationID, -1, null, autoEvents: true, null) { } public DiscordRpcClient(string applicationID, int pipe = -1, ILogger logger = null, bool autoEvents = true, INamedPipeClient client = null) { if (string.IsNullOrEmpty(applicationID)) { throw new ArgumentNullException("applicationID"); } Type typeFromHandle = typeof(JsonConverter); if ((object)typeFromHandle == null) { throw new Exception("JsonConverter Type Not Found"); } ApplicationID = applicationID.Trim(); TargetPipe = pipe; ProcessID = Process.GetCurrentProcess().Id; HasRegisteredUriScheme = false; AutoEvents = autoEvents; SkipIdenticalPresence = true; _logger = logger ?? new NullLogger(); connection = new RpcConnection(ApplicationID, ProcessID, TargetPipe, client ?? new ManagedNamedPipeClient(), (!autoEvents) ? 128u : 0u) { ShutdownOnly = _shutdownOnly, Logger = _logger }; connection.OnRpcMessage += delegate(object sender, IMessage msg) { if (this.OnRpcMessage != null) { this.OnRpcMessage(this, msg); } if (AutoEvents) { ProcessMessage(msg); } }; } public IMessage[] Invoke() { if (AutoEvents) { Logger.Error("Cannot Invoke client when AutomaticallyInvokeEvents has been set."); return new IMessage[0]; } IMessage[] array = connection.DequeueMessages(); foreach (IMessage message in array) { ProcessMessage(message); } return array; } private void ProcessMessage(IMessage message) { if (message == null) { return; } switch (message.Type) { case MessageType.PresenceUpdate: lock (_sync) { if (message is PresenceMessage presenceMessage) { if (CurrentPresence == null) { CurrentPresence = new RichPresence().Merge(presenceMessage.Presence); } else if (presenceMessage.Presence == null) { CurrentPresence = null; } else { CurrentPresence.Merge(presenceMessage.Presence); } presenceMessage.Presence = CurrentPresence; } } break; case MessageType.Ready: if (message is ReadyMessage readyMessage) { lock (_sync) { Configuration = readyMessage.Configuration; CurrentUser = readyMessage.User; } SynchronizeState(); } break; case MessageType.JoinRequest: if (Configuration != null && message is JoinRequestMessage joinRequestMessage) { joinRequestMessage.User.SetConfiguration(Configuration); } break; case MessageType.Subscribe: lock (_sync) { SubscribeMessage subscribeMessage = message as SubscribeMessage; Subscription |= subscribeMessage.Event; } break; case MessageType.Unsubscribe: lock (_sync) { UnsubscribeMessage unsubscribeMessage = message as UnsubscribeMessage; Subscription &= ~unsubscribeMessage.Event; } break; } switch (message.Type) { case MessageType.Ready: if (this.OnReady != null) { this.OnReady(this, message as ReadyMessage); } break; case MessageType.Close: if (this.OnClose != null) { this.OnClose(this, message as CloseMessage); } break; case MessageType.Error: if (this.OnError != null) { this.OnError(this, message as ErrorMessage); } break; case MessageType.PresenceUpdate: if (this.OnPresenceUpdate != null) { this.OnPresenceUpdate(this, message as PresenceMessage); } break; case MessageType.Subscribe: if (this.OnSubscribe != null) { this.OnSubscribe(this, message as SubscribeMessage); } break; case MessageType.Unsubscribe: if (this.OnUnsubscribe != null) { this.OnUnsubscribe(this, message as UnsubscribeMessage); } break; case MessageType.Join: if (this.OnJoin != null) { this.OnJoin(this, message as JoinMessage); } break; case MessageType.Spectate: if (this.OnSpectate != null) { this.OnSpectate(this, message as SpectateMessage); } break; case MessageType.JoinRequest: if (this.OnJoinRequested != null) { this.OnJoinRequested(this, message as JoinRequestMessage); } break; case MessageType.ConnectionEstablished: if (this.OnConnectionEstablished != null) { this.OnConnectionEstablished(this, message as ConnectionEstablishedMessage); } break; case MessageType.ConnectionFailed: if (this.OnConnectionFailed != null) { this.OnConnectionFailed(this, message as ConnectionFailedMessage); } break; default: Logger.Error("Message was queued with no appropriate handle! {0}", message.Type); break; } } public void Respond(JoinRequestMessage request, bool acceptRequest) { if (IsDisposed) { throw new ObjectDisposedException("Discord IPC Client"); } if (connection == null) { throw new ObjectDisposedException("Connection", "Cannot initialize as the connection has been deinitialized"); } if (!IsInitialized) { throw new UninitializedException(); } connection.EnqueueCommand(new RespondCommand { Accept = acceptRequest, UserID = request.User.ID.ToString() }); } public void SetPresence(RichPresence presence) { if (IsDisposed) { throw new ObjectDisposedException("Discord IPC Client"); } if (connection == null) { throw new ObjectDisposedException("Connection", "Cannot initialize as the connection has been deinitialized"); } if (!IsInitialized) { Logger.Warning("The client is not yet initialized, storing the presence as a state instead."); } if (!presence) { if (!SkipIdenticalPresence || CurrentPresence != null) { connection.EnqueueCommand(new PresenceCommand { PID = ProcessID, Presence = null }); } } else { if (presence.HasSecrets() && !HasRegisteredUriScheme) { throw new BadPresenceException("Cannot send a presence with secrets as this object has not registered a URI scheme. Please enable the uri scheme registration in the DiscordRpcClient constructor."); } if (presence.HasParty() && presence.Party.Max < presence.Party.Size) { throw new BadPresenceException("Presence maximum party size cannot be smaller than the current size."); } if (presence.HasSecrets() && !presence.HasParty()) { Logger.Warning("The presence has set the secrets but no buttons will show as there is no party available."); } if (!SkipIdenticalPresence || !presence.Matches(CurrentPresence)) { connection.EnqueueCommand(new PresenceCommand { PID = ProcessID, Presence = presence.Clone() }); } } lock (_sync) { CurrentPresence = presence?.Clone(); } } public RichPresence UpdateDetails(string details) { if (!IsInitialized) { throw new UninitializedException(); } RichPresence richPresence; lock (_sync) { richPresence = ((CurrentPresence != null) ? CurrentPresence.Clone() : new RichPresence()); } richPresence.Details = details; SetPresence(richPresence); return richPresence; } public RichPresence UpdateState(string state) { if (!IsInitialized) { throw new UninitializedException(); } RichPresence richPresence; lock (_sync) { richPresence = ((CurrentPresence != null) ? CurrentPresence.Clone() : new RichPresence()); } richPresence.State = state; SetPresence(richPresence); return richPresence; } public RichPresence UpdateParty(Party party) { if (!IsInitialized) { throw new UninitializedException(); } RichPresence richPresence; lock (_sync) { richPresence = ((CurrentPresence != null) ? CurrentPresence.Clone() : new RichPresence()); } richPresence.Party = party; SetPresence(richPresence); return richPresence; } public RichPresence UpdatePartySize(int size) { if (!IsInitialized) { throw new UninitializedException(); } RichPresence richPresence; lock (_sync) { richPresence = ((CurrentPresence != null) ? CurrentPresence.Clone() : new RichPresence()); } if (richPresence.Party == null) { throw new BadPresenceException("Cannot set the size of the party if the party does not exist"); } richPresence.Party.Size = size; SetPresence(richPresence); return richPresence; } public RichPresence UpdatePartySize(int size, int max) { if (!IsInitialized) { throw new UninitializedException(); } RichPresence richPresence; lock (_sync) { richPresence = ((CurrentPresence != null) ? CurrentPresence.Clone() : new RichPresence()); } if (richPresence.Party == null) { throw new BadPresenceException("Cannot set the size of the party if the party does not exist"); } richPresence.Party.Size = size; richPresence.Party.Max = max; SetPresence(richPresence); return richPresence; } public RichPresence UpdateLargeAsset(string key = null, string tooltip = null) { if (!IsInitialized) { throw new UninitializedException(); } RichPresence richPresence; lock (_sync) { richPresence = ((CurrentPresence != null) ? CurrentPresence.Clone() : new RichPresence()); } if (richPresence.Assets == null) { richPresence.Assets = new Assets(); } richPresence.Assets.LargeImageKey = key ?? richPresence.Assets.LargeImageKey; richPresence.Assets.LargeImageText = tooltip ?? richPresence.Assets.LargeImageText; SetPresence(richPresence); return richPresence; } public RichPresence UpdateSmallAsset(string key = null, string tooltip = null) { if (!IsInitialized) { throw new UninitializedException(); } RichPresence richPresence; lock (_sync) { richPresence = ((CurrentPresence != null) ? CurrentPresence.Clone() : new RichPresence()); } if (richPresence.Assets == null) { richPresence.Assets = new Assets(); } richPresence.Assets.SmallImageKey = key ?? richPresence.Assets.SmallImageKey; richPresence.Assets.SmallImageText = tooltip ?? richPresence.Assets.SmallImageText; SetPresence(richPresence); return richPresence; } public RichPresence UpdateSecrets(Secrets secrets) { if (!IsInitialized) { throw new UninitializedException(); } RichPresence richPresence; lock (_sync) { richPresence = ((CurrentPresence != null) ? CurrentPresence.Clone() : new RichPresence()); } richPresence.Secrets = secrets; SetPresence(richPresence); return richPresence; } public RichPresence UpdateStartTime() { return UpdateStartTime(DateTime.UtcNow); } public RichPresence UpdateStartTime(DateTime time) { if (!IsInitialized) { throw new UninitializedException(); } RichPresence richPresence; lock (_sync) { richPresence = ((CurrentPresence != null) ? CurrentPresence.Clone() : new RichPresence()); } if (richPresence.Timestamps == null) { richPresence.Timestamps = new Timestamps(); } richPresence.Timestamps.Start = time; SetPresence(richPresence); return richPresence; } public RichPresence UpdateEndTime() { return UpdateEndTime(DateTime.UtcNow); } public RichPresence UpdateEndTime(DateTime time) { if (!IsInitialized) { throw new UninitializedException(); } RichPresence richPresence; lock (_sync) { richPresence = ((CurrentPresence != null) ? CurrentPresence.Clone() : new RichPresence()); } if (richPresence.Timestamps == null) { richPresence.Timestamps = new Timestamps(); } richPresence.Timestamps.End = time; SetPresence(richPresence); return richPresence; } public RichPresence UpdateClearTime() { if (!IsInitialized) { throw new UninitializedException(); } RichPresence richPresence; lock (_sync) { richPresence = ((CurrentPresence != null) ? CurrentPresence.Clone() : new RichPresence()); } richPresence.Timestamps = null; SetPresence(richPresence); return richPresence; } public void ClearPresence() { if (IsDisposed) { throw new ObjectDisposedException("Discord IPC Client"); } if (!IsInitialized) { throw new UninitializedException(); } if (connection == null) { throw new ObjectDisposedException("Connection", "Cannot initialize as the connection has been deinitialized"); } SetPresence(null); } public bool RegisterUriScheme(string steamAppID = null, string executable = null) { UriSchemeRegister uriSchemeRegister = new UriSchemeRegister(_logger, ApplicationID, steamAppID, executable); return HasRegisteredUriScheme = uriSchemeRegister.RegisterUriScheme(); } public void Subscribe(EventType type) { SetSubscription(Subscription | type); } [Obsolete("Replaced with Unsubscribe", true)] public void Unubscribe(EventType type) { SetSubscription(Subscription & ~type); } public void Unsubscribe(EventType type) { SetSubscription(Subscription & ~type); } public void SetSubscription(EventType type) { if (IsInitialized) { SubscribeToTypes(Subscription & ~type, isUnsubscribe: true); SubscribeToTypes(~Subscription & type, isUnsubscribe: false); } else { Logger.Warning("Client has not yet initialized, but events are being subscribed too. Storing them as state instead."); } lock (_sync) { Subscription = type; } } private void SubscribeToTypes(EventType type, bool isUnsubscribe) { if (type != 0) { if (IsDisposed) { throw new ObjectDisposedException("Discord IPC Client"); } if (!IsInitialized) { throw new UninitializedException(); } if (connection == null) { throw new ObjectDisposedException("Connection", "Cannot initialize as the connection has been deinitialized"); } if (!HasRegisteredUriScheme) { throw new InvalidConfigurationException("Cannot subscribe/unsubscribe to an event as this application has not registered a URI Scheme. Call RegisterUriScheme()."); } if ((type & EventType.Spectate) == EventType.Spectate) { connection.EnqueueCommand(new SubscribeCommand { Event = ServerEvent.ActivitySpectate, IsUnsubscribe = isUnsubscribe }); } if ((type & EventType.Join) == EventType.Join) { connection.EnqueueCommand(new SubscribeCommand { Event = ServerEvent.ActivityJoin, IsUnsubscribe = isUnsubscribe }); } if ((type & EventType.JoinRequest) == EventType.JoinRequest) { connection.EnqueueCommand(new SubscribeCommand { Event = ServerEvent.ActivityJoinRequest, IsUnsubscribe = isUnsubscribe }); } } } public void SynchronizeState() { if (!IsInitialized) { throw new UninitializedException(); } SetPresence(CurrentPresence); if (HasRegisteredUriScheme) { SubscribeToTypes(Subscription, isUnsubscribe: false); } } public bool Initialize() { if (IsDisposed) { throw new ObjectDisposedException("Discord IPC Client"); } if (IsInitialized) { throw new UninitializedException("Cannot initialize a client that is already initialized"); } if (connection == null) { throw new ObjectDisposedException("Connection", "Cannot initialize as the connection has been deinitialized"); } return IsInitialized = connection.AttemptConnection(); } public void Deinitialize() { if (!IsInitialized) { throw new UninitializedException("Cannot deinitialize a client that has not been initalized."); } connection.Close(); IsInitialized = false; } public void Dispose() { if (!IsDisposed) { if (IsInitialized) { Deinitialize(); } IsDisposed = true; } } } [Flags] public enum EventType { None = 0, Spectate = 1, Join = 2, JoinRequest = 4 } [Serializable] [JsonObject(/*Could not decode attribute arguments.*/)] public class BaseRichPresence { protected internal string _state; protected internal string _details; [JsonProperty(/*Could not decode attribute arguments.*/)] public string State { get { return _state; } set { if (!ValidateString(value, out _state, 128, Encoding.UTF8)) { throw new StringOutOfRangeException("State", 0, 128); } } } [JsonProperty(/*Could not decode attribute arguments.*/)] public string Details { get { return _details; } set { if (!ValidateString(value, out _details, 128, Encoding.UTF8)) { throw new StringOutOfRangeException(128); } } } [JsonProperty(/*Could not decode attribute arguments.*/)] public Timestamps Timestamps { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public Assets Assets { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public Party Party { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public Secrets Secrets { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] [Obsolete("This was going to be used, but was replaced by JoinSecret instead")] private bool Instance { get; set; } public bool HasTimestamps() { return Timestamps != null && (Timestamps.Start.HasValue || Timestamps.End.HasValue); } public bool HasAssets() { return Assets != null; } public bool HasParty() { return Party != null && Party.ID != null; } public bool HasSecrets() { return Secrets != null && (Secrets.JoinSecret != null || Secrets.SpectateSecret != null); } internal static bool ValidateString(string str, out string result, int bytes, Encoding encoding) { result = str; if (str == null) { return true; } string str2 = str.Trim(); if (!str2.WithinLength(bytes, encoding)) { return false; } result = str2.GetNullOrString(); return true; } public static implicit operator bool(BaseRichPresence presesnce) { return presesnce != null; } internal virtual bool Matches(RichPresence other) { if (other == null) { return false; } if (State != other.State || Details != other.Details) { return false; } if (Timestamps != null) { if (other.Timestamps == null || other.Timestamps.StartUnixMilliseconds != Timestamps.StartUnixMilliseconds || other.Timestamps.EndUnixMilliseconds != Timestamps.EndUnixMilliseconds) { return false; } } else if (other.Timestamps != null) { return false; } if (Secrets != null) { if (other.Secrets == null || other.Secrets.JoinSecret != Secrets.JoinSecret || other.Secrets.MatchSecret != Secrets.MatchSecret || other.Secrets.SpectateSecret != Secrets.SpectateSecret) { return false; } } else if (other.Secrets != null) { return false; } if (Party != null) { if (other.Party == null || other.Party.ID != Party.ID || other.Party.Max != Party.Max || other.Party.Size != Party.Size || other.Party.Privacy != Party.Privacy) { return false; } } else if (other.Party != null) { return false; } if (Assets != null) { if (other.Assets == null || other.Assets.LargeImageKey != Assets.LargeImageKey || other.Assets.LargeImageText != Assets.LargeImageText || other.Assets.SmallImageKey != Assets.SmallImageKey || other.Assets.SmallImageText != Assets.SmallImageText) { return false; } } else if (other.Assets != null) { return false; } return Instance == other.Instance; } } [Serializable] public class Secrets { private string _matchSecret; private string _joinSecret; private string _spectateSecret; [Obsolete("This feature has been deprecated my Mason in issue #152 on the offical library. Was originally used as a Notify Me feature, it has been replaced with Join / Spectate.")] [JsonProperty(/*Could not decode attribute arguments.*/)] public string MatchSecret { get { return _matchSecret; } set { if (!BaseRichPresence.ValidateString(value, out _matchSecret, 128, Encoding.UTF8)) { throw new StringOutOfRangeException(128); } } } [JsonProperty(/*Could not decode attribute arguments.*/)] public string JoinSecret { get { return _joinSecret; } set { if (!BaseRichPresence.ValidateString(value, out _joinSecret, 128, Encoding.UTF8)) { throw new StringOutOfRangeException(128); } } } [JsonProperty(/*Could not decode attribute arguments.*/)] public string SpectateSecret { get { return _spectateSecret; } set { if (!BaseRichPresence.ValidateString(value, out _spectateSecret, 128, Encoding.UTF8)) { throw new StringOutOfRangeException(128); } } } public static Encoding Encoding => Encoding.UTF8; public static int SecretLength => 128; public static string CreateSecret(Random random) { byte[] array = new byte[SecretLength]; random.NextBytes(array); return Encoding.GetString(array); } public static string CreateFriendlySecret(Random random) { string text = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; string text2 = ""; for (int i = 0; i < SecretLength; i++) { text2 += text[random.Next(text.Length)]; } return text2; } } [Serializable] public class Assets { private string _largeimagekey; private string _largeimagetext; private string _smallimagekey; private string _smallimagetext; private ulong? _largeimageID; private ulong? _smallimageID; [JsonProperty(/*Could not decode attribute arguments.*/)] public string LargeImageKey { get { return _largeimagekey; } set { if (!BaseRichPresence.ValidateString(value, out _largeimagekey, 32, Encoding.UTF8)) { throw new StringOutOfRangeException(32); } _largeimageID = null; } } [JsonProperty(/*Could not decode attribute arguments.*/)] public string LargeImageText { get { return _largeimagetext; } set { if (!BaseRichPresence.ValidateString(value, out _largeimagetext, 128, Encoding.UTF8)) { throw new StringOutOfRangeException(128); } } } [JsonProperty(/*Could not decode attribute arguments.*/)] public string SmallImageKey { get { return _smallimagekey; } set { if (!BaseRichPresence.ValidateString(value, out _smallimagekey, 32, Encoding.UTF8)) { throw new StringOutOfRangeException(32); } _smallimageID = null; } } [JsonProperty(/*Could not decode attribute arguments.*/)] public string SmallImageText { get { return _smallimagetext; } set { if (!BaseRichPresence.ValidateString(value, out _smallimagetext, 128, Encoding.UTF8)) { throw new StringOutOfRangeException(128); } } } [JsonIgnore] public ulong? LargeImageID => _largeimageID; [JsonIgnore] public ulong? SmallImageID => _smallimageID; internal void Merge(Assets other) { _smallimagetext = other._smallimagetext; _largeimagetext = other._largeimagetext; if (ulong.TryParse(other._largeimagekey, out var result)) { _largeimageID = result; } else { _largeimagekey = other._largeimagekey; _largeimageID = null; } if (ulong.TryParse(other._smallimagekey, out var result2)) { _smallimageID = result2; return; } _smallimagekey = other._smallimagekey; _smallimageID = null; } } [Serializable] public class Timestamps { public static Timestamps Now => new Timestamps(DateTime.UtcNow); [JsonIgnore] public DateTime? Start { get; set; } [JsonIgnore] public DateTime? End { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public ulong? StartUnixMilliseconds { get { return Start.HasValue ? new ulong?(ToUnixMilliseconds(Start.Value)) : null; } set { Start = (value.HasValue ? new DateTime?(FromUnixMilliseconds(value.Value)) : null); } } [JsonProperty(/*Could not decode attribute arguments.*/)] public ulong? EndUnixMilliseconds { get { return End.HasValue ? new ulong?(ToUnixMilliseconds(End.Value)) : null; } set { End = (value.HasValue ? new DateTime?(FromUnixMilliseconds(value.Value)) : null); } } public static Timestamps FromTimeSpan(double seconds) { return FromTimeSpan(TimeSpan.FromSeconds(seconds)); } public static Timestamps FromTimeSpan(TimeSpan timespan) { return new Timestamps { Start = DateTime.UtcNow, End = DateTime.UtcNow + timespan }; } public Timestamps() { Start = null; End = null; } public Timestamps(DateTime start, DateTime? end = null) { Start = start; End = end; } public static DateTime FromUnixMilliseconds(ulong unixTime) { return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddMilliseconds(Convert.ToDouble(unixTime)); } public static ulong ToUnixMilliseconds(DateTime date) { DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); return Convert.ToUInt64((date - dateTime).TotalMilliseconds); } } [Serializable] public class Party { public enum PrivacySetting { Private, Public } private string _partyid; [JsonProperty(/*Could not decode attribute arguments.*/)] public string ID { get { return _partyid; } set { _partyid = value.GetNullOrString(); } } [JsonIgnore] public int Size { get; set; } [JsonIgnore] public int Max { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] public PrivacySetting Privacy { get; set; } [JsonProperty(/*Could not decode attribute arguments.*/)] private int[] _size { get { int num = Math.Max(1, Size); return new int[2] { num, Math.Max(num, Max) }; } set { if (value.Length != 2) { Size = 0; Max = 0; } else { Size = value[0]; Max = value[1]; } } } } public class Button { private string _label; private string _url; [JsonProperty("label")] public string Label { get { return _label; } set { if (!BaseRichPresence.ValidateString(value, out _label, 32, Encoding.UTF8)) { throw new StringOutOfRangeException(32); } } } [JsonProperty("url")] public string Url { get { return _url; } set { if (!BaseRichPresence.ValidateString(value, out _url, 512, Encoding.UTF8)) { throw new StringOutOfRangeException(512); } if (!Uri.TryCreate(_url, UriKind.Absolute, out Uri _)) { throw new ArgumentException("Url must be a valid URI"); } } } } public sealed class RichPresence : BaseRichPresence { [JsonProperty(/*Could not decode attribute arguments.*/)] public Button[] Buttons { get; set; } public bool HasButtons() { return Buttons != null && Buttons.Length != 0; } public RichPresence WithState(string state) { base.State = state; return this; } public RichPresence WithDetails(string details) { base.Details = details; return this; } public RichPresence WithTimestamps(Timestamps timestamps) { base.Timestamps = timestamps; return this; } public RichPresence WithAssets(Assets assets) { base.Assets = assets; return this; } public RichPresence WithParty(Party party) { base.Party = party; return this; } public RichPresence WithSecrets(Secrets secrets) { base.Secrets = secrets; return this; } public RichPresence Clone() { RichPresence richPresence = new RichPresence(); richPresence.State = ((_state != null) ? (_state.Clone() as string) : null); richPresence.Details = ((_details != null) ? (_details.Clone() as string) : null); richPresence.Buttons = ((!HasButtons()) ? null : (Buttons.Clone() as Button[])); richPresence.Secrets = ((!HasSecrets()) ? null : new Secrets { JoinSecret = ((base.Secrets.JoinSecret != null) ? (base.Secrets.JoinSecret.Clone() as string) : null), SpectateSecret = ((base.Secrets.SpectateSecret != null) ? (base.Secrets.SpectateSecret.Clone() as string) : null) }); richPresence.Timestamps = ((!HasTimestamps()) ? null : new Timestamps { Start = base.Timestamps.Start, End = base.Timestamps.End }); richPresence.Assets = ((!HasAssets()) ? null : new Assets { LargeImageKey = ((base.Assets.LargeImageKey != null) ? (base.Assets.LargeImageKey.Clone() as string) : null), LargeImageText = ((base.Assets.LargeImageText != null) ? (base.Assets.LargeImageText.Clone() as string) : null), SmallImageKey = ((base.Assets.SmallImageKey != null) ? (base.Assets.SmallImageKey.Clone() as string) : null), SmallImageText = ((base.Assets.SmallImageText != null) ? (base.Assets.SmallImageText.Clone() as string) : null) }); richPresence.Party = ((!HasParty()) ? null : new Party { ID = base.Party.ID, Size = base.Party.Size, Max = base.Party.Max, Privacy = base.Party.Privacy }); return richPresence; } internal RichPresence Merge(BaseRichPresence presence) { _state = presence.State; _details = presence.Details; base.Party = presence.Party; base.Timestamps = presence.Timestamps; base.Secrets = presence.Secrets; if (presence.HasAssets()) { if (!HasAssets()) { base.Assets = presence.Assets; } else { base.Assets.Merge(presence.Assets); } } else { base.Assets = null; } return this; } internal override bool Matches(RichPresence other) { if (!base.Matches(other)) { return false; } if ((Buttons == null) ^ (other.Buttons == null)) { return false; } if (Buttons != null) { if (Buttons.Length != other.Buttons.Length) { return false; } for (int i = 0; i < Buttons.Length; i++) { Button button = Buttons[i]; Button button2 = other.Buttons[i]; if (button.Label != button2.Label || button.Url != button2.Url) { return false; } } } return true; } public static implicit operator bool(RichPresence presesnce) { return presesnce != null; } } internal sealed class RichPresenceResponse : BaseRichPresence { [JsonProperty("application_id")] public string ClientID { get; private set; } [JsonProperty("name")] public string Name { get; private set; } } public class User { public enum AvatarFormat { PNG, JPEG, WebP, GIF } public enum AvatarSize { x16 = 0x10, x32 = 0x20, x64 = 0x40, x128 = 0x80, x256 = 0x100, x512 = 0x200, x1024 = 0x400, x2048 = 0x800 } [Flags] public enum Flag { None = 0, Employee = 1, Partner = 2, HypeSquad = 4, BugHunter = 8, HouseBravery = 0x40, HouseBrilliance = 0x80, HouseBalance = 0x100, EarlySupporter = 0x200, TeamUser = 0x400 } public enum PremiumType { None, NitroClassic, Nitro } [JsonProperty("id")] public ulong ID { get; private set; } [JsonProperty("username")] public string Username { get; private set; } [JsonProperty("discriminator")] public int Discriminator { get; private set; } [JsonProperty("avatar")] public string Avatar { get; private set; } [JsonProperty("flags")] public Flag Flags { get; private set; } [JsonProperty("premium_type")] public PremiumType Premium { get; private set; } public string CdnEndpoint { get; private set; } internal User() { CdnEndpoint = "cdn.discordapp.com"; } internal void SetConfiguration(Configuration configuration) { CdnEndpoint = configuration.CdnHost; } public string GetAvatarURL(AvatarFormat format, AvatarSize size = AvatarSize.x128) { string text = "/avatars/" + ID + "/" + Avatar; if (string.IsNullOrEmpty(Avatar)) { if (format != 0) { throw new BadImageFormatException("The user has no avatar and the requested format " + format.ToString() + " is not supported. (Only supports PNG)."); } text = "/embed/avatars/" + Discriminator % 5; } return $"https://{CdnEndpoint}{text}{GetAvatarExtension(format)}?size={(int)size}"; } public string GetAvatarExtension(AvatarFormat format) { return "." + format.ToString().ToLowerInvariant(); } public override string ToString() { return Username + "#" + Discriminator.ToString("D4"); } } } namespace DiscordRPC.RPC { internal class RpcConnection : IDisposable { public static readonly int VERSION = 1; public static readonly int POLL_RATE = 1000; private static readonly bool CLEAR_ON_SHUTDOWN = true; private static readonly bool LOCK_STEP = false; private ILogger _logger; private RpcState _state; private readonly object l_states = new object(); private Configuration _configuration = null; private readonly object l_config = new object(); private volatile bool aborting = false; private volatile bool shutdown = false; private string applicationID; private int processID; private long nonce; private Thread thread; private INamedPipeClient namedPipe; private int targetPipe; private readonly object l_rtqueue = new object(); private readonly uint _maxRtQueueSize; private Queue<ICommand> _rtqueue; private readonly object l_rxqueue = new object(); private readonly uint _maxRxQueueSize; private Queue<IMessage> _rxqueue; private AutoResetEvent queueUpdatedEvent = new AutoResetEvent(initialState: false); private BackoffDelay delay; public ILogger Logger { get { return _logger; } set { _logger = value; if (namedPipe != null) { namedPipe.Logger = value; } } } public RpcState State { get { RpcState result = RpcState.Disconnected; lock (l_states) { result = _state; } return result; } } public Configuration Configuration { get { Configuration result = null; lock (l_config) { result = _configuration; } return result; } } public bool IsRunning => thread != null; public bool ShutdownOnly { get; set; } public event OnRpcMessageEvent OnRpcMessage; public RpcConnection(string applicationID, int processID, int targetPipe, INamedPipeClient client, uint maxRxQueueSize = 128u, uint maxRtQueueSize = 512u) { this.applicationID = applicationID; this.processID = processID; this.targetPipe = targetPipe; namedPipe = client; ShutdownOnly = true; Logger = new ConsoleLogger(); delay = new BackoffDelay(500, 60000); _maxRtQueueSize = maxRtQueueSize; _rtqueue = new Queue<ICommand>((int)(_maxRtQueueSize + 1)); _maxRxQueueSize = maxRxQueueSize; _rxqueue = new Queue<IMessage>((int)(_maxRxQueueSize + 1)); nonce = 0L; } private long GetNextNonce() { nonce++; return nonce; } internal void EnqueueCommand(ICommand command) { Logger.Trace("Enqueue Command: " + command.GetType().FullName); if (aborting || shutdown) { return; } lock (l_rtqueue) { if (_rtqueue.Count == _maxRtQueueSize) { Logger.Error("Too many enqueued commands, dropping oldest one. Maybe you are pushing new presences to fast?"); _rtqueue.Dequeue(); } _rtqueue.Enqueue(command); } } private void EnqueueMessage(IMessage message) { try { if (this.OnRpcMessage != null) { this.OnRpcMessage(this, message); } } catch (Exception ex) { Logger.Error("Unhandled Exception while processing event: {0}", ex.GetType().FullName); Logger.Error(ex.Message); Logger.Error(ex.StackTrace); } if (_maxRxQueueSize == 0) { Logger.Trace("Enqueued Message, but queue size is 0."); return; } Logger.Trace("Enqueue Message: " + message.Type); lock (l_rxqueue) { if (_rxqueue.Count == _maxRxQueueSize) { Logger.Warning("Too many enqueued messages, dropping oldest one."); _rxqueue.Dequeue(); } _rxqueue.Enqueue(message); } } internal IMessage DequeueMessage() { lock (l_rxqueue) { if (_rxqueue.Count == 0) { return null; } return _rxqueue.Dequeue(); } } internal IMessage[] DequeueMessages() { lock (l_rxqueue) { IMessage[] result = _rxqueue.ToArray(); _rxqueue.Clear(); return result; } } private void MainLoop() { Logger.Info("RPC Connection Started"); if (Logger.Level <= LogLevel.Trace) { Logger.Trace("============================"); Logger.Trace("Assembly: " + Assembly.GetAssembly(typeof(RichPresence)).FullName); Logger.Trace("Pipe: " + namedPipe.GetType().FullName); Logger.Trace("Platform: " + Environment.OSVersion.ToString()); Logger.Trace("applicationID: " + applicationID); Logger.Trace("targetPipe: " + targetPipe); ILogger logger = Logger; int pOLL_RATE = POLL_RATE; logger.Trace("POLL_RATE: " + pOLL_RATE); ILogger logger2 = Logger; uint maxRtQueueSize = _maxRtQueueSize; logger2.Trace("_maxRtQueueSize: " + maxRtQueueSize); ILogger logger3 = Logger; maxRtQueueSize = _maxRxQueueSize; logger3.Trace("_maxRxQueueSize: " + maxRtQueueSize); Logger.Trace("============================"); } while (!aborting && !shutdown) { try { if (namedPipe == null) { Logger.Error("Something bad has happened with our pipe client!"); aborting = true; return; } Logger.Trace("Connecting to the pipe through the {0}", namedPipe.GetType().FullName); if (namedPipe.Connect(targetPipe)) { Logger.Trace("Connected to the pipe. Attempting to establish handshake..."); EnqueueMessage(new ConnectionEstablishedMessage { ConnectedPipe = namedPipe.ConnectedPipe }); EstablishHandshake(); Logger.Trace("Connection Established. Starting reading loop..."); bool flag = true; while (flag && !aborting && !shutdown && namedPipe.IsConnected) { if (namedPipe.ReadFrame(out var frame)) { Logger.Trace("Read Payload: {0}", frame.Opcode); switch (frame.Opcode) { case Opcode.Close: { ClosePayload @object = frame.GetObject<ClosePayload>(); Logger.Warning("We have been told to terminate by discord: ({0}) {1}", @object.Code, @object.Reason); EnqueueMessage(new CloseMessage { Code = @object.Code, Reason = @object.Reason }); flag = false; break; } case Opcode.Ping: Logger.Trace("PING"); frame.Opcode = Opcode.Pong; namedPipe.WriteFrame(frame); break; case Opcode.Pong: Logger.Trace("PONG"); break; case Opcode.Frame: { if (shutdown) { Logger.Warning("Skipping frame because we are shutting down."); break; } if (frame.Data == null) { Logger.Error("We received no data from the frame so we cannot get the event payload!"); break; } EventPayload eventPayload = null; try { eventPayload = frame.GetObject<EventPayload>(); } catch (Exception ex) { Logger.Error("Failed to parse event! " + ex.Message); Logger.Error("Data: " + frame.Message); } try { if (eventPayload != null) { ProcessFrame(eventPayload); } } catch (Exception ex2) { Logger.Error("Failed to process event! " + ex2.Message); Logger.Error("Data: " + frame.Message); } break; } default: Logger.Error("Invalid opcode: {0}", frame.Opcode); flag = false; break; } } if (!aborting && namedPipe.IsConnected) { ProcessCommandQueue(); queueUpdatedEvent.WaitOne(POLL_RATE); } } Logger.Trace("Left main read loop for some reason. Aborting: {0}, Shutting Down: {1}", aborting, shutdown); } else { Logger.Error("Failed to connect for some reason."); EnqueueMessage(new ConnectionFailedMessage { FailedPipe = targetPipe }); } if (!aborting && !shutdown) { long num = delay.NextDelay(); Logger.Trace("Waiting {0}ms before attempting to connect again", num); Thread.Sleep(delay.NextDelay()); } } catch (Exception ex3) { Logger.Error("Unhandled Exception: {0}", ex3.GetType().FullName); Logger.Error(ex3.Message); Logger.Error(ex3.StackTrace); } finally { if (namedPipe.IsConnected) { Logger.Trace("Closing the named pipe."); namedPipe.Close(); } SetConnectionState(RpcState.Disconnected); } } Logger.Trace("Left Main Loop"); if (namedPipe != null) { namedPipe.Dispose(); } Logger.Info("Thread Terminated, no longer performing RPC connection."); } private void ProcessFrame(EventPayload response) { //IL_0210: Unknown result type (might be due to invalid IL or missing references) //IL_0217: Expected O, but got Unknown Logger.Info("Handling Response. Cmd: {0}, Event: {1}", response.Command, response.Event); if (response.Event.HasValue && response.Event.Value == ServerEvent.Error) { Logger.Error("Error received from the RPC"); ErrorMessage @object = response.GetObject<ErrorMessage>(); Logger.Error("Server responded with an error message: ({0}) {1}", @object.Code.ToString(), @object.Message); EnqueueMessage(@object); } else if (State == RpcState.Connecting && response.Command == Command.Dispatch && response.Event.HasValue && response.Event.Value == ServerEvent.Ready) { Logger.Info("Connection established with the RPC"); SetConnectionState(RpcState.Connected); delay.Reset(); ReadyMessage object2 = response.GetObject<ReadyMessage>(); lock (l_config) { _configuration = object2.Configuration; object2.User.SetConfiguration(_configuration); } EnqueueMessage(object2); } else if (State == RpcState.Connected) { switch (response.Command) { case Command.Dispatch: ProcessDispatch(response); break; case Command.SetActivity: { if (response.Data == null) { EnqueueMessage(new PresenceMessage()); break; } RichPresenceResponse object3 = response.GetObject<RichPresenceResponse>(); EnqueueMessage(new PresenceMessage(object3)); break; } case Command.Subscribe: case Command.Unsubscribe: { JsonSerializer val = new JsonSerializer(); ((Collection<JsonConverter>)(object)val.Converters).Add((JsonConverter)(object)new EnumSnakeCaseConverter()); ServerEvent value = response.GetObject<EventPayload>().Event.Value; if (response.Command == Command.Subscribe) { EnqueueMessage(new SubscribeMessage(value)); } else { EnqueueMessage(new UnsubscribeMessage(value)); } break; } case Command.SendActivityJoinInvite: Logger.Trace("Got invite response ack."); break; case Command.CloseActivityJoinRequest: Logger.Trace("Got invite response reject ack."); break; default: Logger.Error("Unkown frame was received! {0}", response.Command); break; } } else { Logger.Trace("Received a frame while we are disconnected. Ignoring. Cmd: {0}, Event: {1}", response.Command, response.Event); } } private void ProcessDispatch(EventPayload response) { if (response.Command == Command.Dispatch && response.Event.HasValue) { switch (response.Event.Value) { case ServerEvent.ActivitySpectate: { SpectateMessage object3 = response.GetObject<SpectateMessage>(); EnqueueMessage(object3); break; } case ServerEvent.ActivityJoin: { JoinMessage object2 = response.GetObject<JoinMessage>(); EnqueueMessage(object2); break; } case ServerEvent.ActivityJoinRequest: { JoinRequestMessage @object = response.GetObject<JoinRequestMessage>(); EnqueueMessage(@object); break; } default: Logger.Warning("Ignoring {0}", response.Event.Value); break; } } } private void ProcessCommandQueue() { if (State != RpcState.Connected) { return; } if (aborting) { Logger.Warning("We have been told to write a queue but we have also been aborted."); } bool flag = true; ICommand command = null; while (flag && namedPipe.IsConnected) { lock (l_rtqueue) { flag = _rtqueue.Count > 0; if (!flag) { break; } command = _rtqueue.Peek(); } if (shutdown || (!aborting && LOCK_STEP)) { flag = false; } IPayload payload = command.PreparePayload(GetNextNonce()); Logger.Trace("Attempting to send payload: " + payload.Command); PipeFrame frame = default(PipeFrame); if (command is CloseCommand) { SendHandwave(); Logger.Trace("Handwave sent, ending queue processing."); lock (l_rtqueue) { _rtqueue.Dequeue(); break; } } if (aborting) { Logger.Warning("- skipping frame because of abort."); lock (l_rtqueue) { _rtqueue.Dequeue(); } continue; } frame.SetObject(Opcode.Frame, payload); Logger.Trace("Sending payload: " + payload.Command); if (namedPipe.WriteFrame(frame)) { Logger.Trace("Sent Successfully."); lock (l_rtqueue) { _rtqueue.Dequeue(); } continue; } Logger.Warning("Something went wrong during writing!"); break; } } private void EstablishHandshake() { Logger.Trace("Attempting to establish a handshake..."); if (State != 0) { Logger.Error("State must be disconnected in order to start a handshake!"); return; } Logger.Trace("Sending Handshake..."); if (!namedPipe.WriteFrame(new PipeFrame(Opcode.Handshake, new Handshake { Version = VERSION, ClientID = applicationID }))) { Logger.Error("Failed to write a handshake."); } else { SetConnectionState(RpcState.Connecting); } } private void SendHandwave() { Logger.Info("Attempting to wave goodbye..."); if (State == RpcState.Disconnected) { Logger.Error("State must NOT be disconnected in order to send a handwave!"); } else if (!namedPipe.WriteFrame(new PipeFrame(Opcode.Close, new Handshake { Version = VERSION, ClientID = applicationID }))) { Logger.Error("failed to write a handwave."); } } public bool AttemptConnection() { Logger.Info("Attempting a new connection"); if (thread != null) { Logger.Error("Cannot attempt a new connection as the previous connection thread is not null!"); return false; } if (State != 0) { Logger.Warning("Cannot attempt a new connection as the previous connection hasn't changed state yet."); return false; } if (aborting) { Logger.Error("Cannot attempt a new connection while aborting!"); return false; } thread = new Thread(MainLoop); thread.Name = "Discord IPC Thread"; thread.IsBackground = true; thread.Start(); return true; } private void SetConnectionState(RpcState state) { Logger.Trace("Setting the connection state to {0}", state.ToString().ToSnakeCase().ToUpperInvariant()); lock (l_states) { _state = state; } } public void Shutdown() { Logger.Trace("Initiated shutdown procedure"); shutdown = true; lock (l_rtqueue) { _rtqueue.Clear(); if (CLEAR_ON_SHUTDOWN) { _rtqueue.Enqueue(new PresenceCommand { PID = processID, Presence = null }); } _rtqueue.Enqueue(new CloseCommand()); } queueUpdatedEvent.Set(); } public void Close() { if (thread == null) { Logger.Error("Cannot close as it is not available!"); return; } if (aborting) { Logger.Error("Cannot abort as it has already been aborted"); return; } if (ShutdownOnly) { Shutdown(); return; } Logger.Trace("Updating Abort State..."); aborting = true; queueUpdatedEvent.Set(); } public void Dispose() { ShutdownOnly = false; Close(); } } internal enum RpcState { Disconnected, Connecting, Connected } } namespace DiscordRPC.RPC.Payload { internal class ClosePayload : IPayload { [JsonProperty("code")] public int Code { get; set; } [JsonProperty("message")] public string Reason { get; set; } } internal enum Command { [EnumValue("DISPATCH")] Dispatch, [EnumValue("SET_ACTIVITY")] SetActivity, [EnumValue("SUBSCRIBE")] Subscribe, [EnumValue("UNSUBSCRIBE")] Unsubscribe, [EnumValue("SEND_ACTIVITY_JOIN_INVITE")] SendActivityJoinInvite, [EnumValue("CLOSE_ACTIVITY_JOIN_REQUEST")] CloseActivityJoinRequest, [Obsolete("This value is appart of the RPC API and is not supported by this library.", true)] Authorize, [Obsolete("This value is appart of the RPC API and is not supported by this library.", true)] Authenticate, [Obsolete("This value is appart of the RPC API and is not supported by this library.", true)] GetGuild, [Obsolete("This value is appart of the RPC API and is not supported by this library.", true)] GetGuilds, [Obsolete("This value is appart of the RPC API and is not supported by this library.", true)] GetChannel, [Obsolete("This value is appart of the RPC API and is not supported by this library.", true)] GetChannels, [Obsolete("This value is appart of the RPC API and is not supported by this library.", true)] SetUserVoiceSettings, [Obsolete("This value is appart of the RPC API and is not supported by this library.", true)] SelectVoiceChannel, [Obsolete("This value is appart of the RPC API and is not supported by this library.", true)] GetSelectedVoiceChannel, [Obsolete("This value is appart of the RPC API and is not supported by this library.", true)] SelectTextChannel, [Obsolete("This value is appart of the RPC API and is not supported by this library.", true)] GetVoiceSettings, [Obsolete("This value is appart of the RPC API and is not supported by this library.", true)] SetVoiceSettings, [Obsolete("This value is appart of the RPC API and is not supported by this library.", true)] CaptureShortcut } internal abstract class IPayload { [JsonProperty("cmd")] [JsonConverter(typeof(EnumSnakeCaseConverter))] public Command Command { get; set; } [JsonProperty("nonce")] public string Nonce { get; set; } protected IPayload() { } protected IPayload(long nonce) { Nonce = nonce.ToString(); } public override string ToString() { return "Payload || Command: " + Command.ToString() + ", Nonce: " + ((Nonce != null) ? Nonce.ToString() : "NULL"); } } internal class ArgumentPayload : IPayload { [JsonProperty(/*Could not decode attribute arguments.*/)] public JObject Arguments { get; set; } public ArgumentPayload() { Arguments = null; } public ArgumentPayload(long nonce) : base(nonce) { Arguments = null; } public ArgumentPayload(object args, long nonce) : base(nonce) { SetObject(args); } public void SetObject(object obj) { Arguments = JObject.FromObject(obj); } public T GetObject<T>() { return ((JToken)Arguments).ToObject<T>(); } public override string ToString() { return "Argument " + base.ToString(); } } internal class EventPayload : IPayload { [JsonProperty(/*Could not decode attribute arguments.*/)] public JObject Data { get; set; } [JsonProperty("evt")] [JsonConverter(typeof(EnumSnakeCaseConverter))] public ServerEvent? Event { get; set; } public EventPayload() { Data = null; } public EventPayload(long nonce) : base(nonce) { Data = null; } public T GetObject<T>() { if (Data == null) { return default(T); } return ((JToken)Data).ToObject<T>(); } public override string ToString() { return "Event " + base.ToString() + ", Event: " + (Event.HasValue ? Event.ToString() : "N/A"); } } internal enum ServerEvent { [EnumValue("READY")] Ready, [EnumValue("ERROR")] Error, [EnumValue("ACTIVITY_JOIN")] ActivityJoin, [EnumValue("ACTIVITY_SPECTATE")] ActivitySpectate, [EnumValue("ACTIVITY_JOIN_REQUEST")] ActivityJoinRequest } } namespace DiscordRPC.RPC.Commands { internal class CloseCommand : ICommand { [JsonProperty("close_reason")] public string value = "Unity 5.5 doesn't handle thread aborts. Can you please close me discord?"; [JsonProperty("pid")] public int PID { get; set; } public IPayload PreparePayload(long nonce) { return new ArgumentPayload { Command = Command.Dispatch, Nonce = null, Arguments = null }; } } internal interface ICommand { IPayload PreparePayload(long nonce); } internal class PresenceCommand : ICommand { [JsonProperty("pid")] public int PID { get; set; } [JsonProperty("activity")] public RichPresence Presence { get; set; } public IPayload PreparePayload(long nonce) { return new ArgumentPayload(this, nonce) { Command = Command.SetActivity }; } } internal class RespondCommand : ICommand { [JsonProperty("user_id")] public string UserID { get; set; } [JsonIgnore] public bool Accept { get; set; } public IPayload PreparePayload(long nonce) { return new ArgumentPayload(this, nonce) { Command = (Accept ? Command.SendActivityJoinInvite : Command.CloseActivityJoinRequest) }; } } internal class SubscribeCommand : ICommand { public ServerEvent Event { get; set; } public bool IsUnsubscribe { get; set; } public IPayload PreparePayload(long nonce) { return new EventPayload(nonce) { Command = (IsUnsubscribe ? Command.Unsubscribe : Command.Subscribe), Event = Event }; } } } namespace DiscordRPC.Registry { internal interface IUriSchemeCreator { bool RegisterUriScheme(UriSchemeRegister register); } internal class MacUriSchemeCreator : IUriSchemeCreator { private ILogger logger; public MacUriSchemeCreator(ILogger logger) { this.logger = logger; } public bool RegisterUriScheme(UriSchemeRegister register) { string executablePath = register.ExecutablePath; if (string.IsNullOrEmpty(executablePath)) { logger.Error("Failed to register because the application could not be located."); return false; } logger.Trace("Registering Steam Command"); string text = executablePath; if (register.UsingSteamApp) { text = "steam://rungameid/" + register.SteamAppID; } else { logger.Warning("This library does not fully support MacOS URI Scheme Registration."); } string text2 = "~/Library/Application Support/discord/games"; DirectoryInfo directoryInfo = Directory.CreateDirectory(text2); if (!directoryInfo.Exists) { logger.Error("Failed to register because {0} does not exist", text2); return false; } File.WriteAllText(text2 + "/" + register.ApplicationID + ".json", "{ \"command\": \"" + text + "\" }"); logger.Trace("Registered {0}, {1}", text2 + "/" + register.ApplicationID + ".json", text); return true; } } internal class UnixUriSchemeCreator : IUriSchemeCreator { private ILogger logger; public UnixUriSchemeCreator(ILogger logger) { this.logger = logger; } public bool RegisterUriScheme(UriSchemeRegister register) { string environmentVariable = Environment.GetEnvironmentVariable("HOME"); if (string.IsNullOrEmpty(environmentVariable)) { logger.Error("Failed to register because the HOME variable was not set."); return false; } string executablePath = register.ExecutablePath; if (string.IsNullOrEmpty(executablePath)) { logger.Error("Failed to register because the application was not located."); return false; } string text = null; text = ((!register.UsingSteamApp) ? executablePath : ("xdg-open steam://rungameid/" + register.SteamAppID)); string format = "[Desktop Entry]\r\nName=Game {0}\r\nExec={1} %u\r\nType=Application\r\nNoDisplay=true\r\nCategories=Discord;Games;\r\nMimeType=x-scheme-handler/discord-{2}"; string text2 = string.Format(format, register.ApplicationID, text, register.ApplicationID); string text3 = "/discord-" + register.ApplicationID + ".desktop"; string text4 = environmentVariable + "/.local/share/applications"; DirectoryInfo directoryInfo = Directory.CreateDirectory(text4); if (!directoryInfo.Exists) { logger.Error("Failed to register because {0} does not exist", text4); return false; } File.WriteAllText(text4 + text3, text2); if (!RegisterMime(register.ApplicationID)) { logger.Error("Failed to register because the Mime failed."); return false; } logger.Trace("Registered {0}, {1}, {2}", text4 + text3, text2, text); return true; } private bool RegisterMime(string appid) { string format = "default discord-{0}.desktop x-scheme-handler/discord-{0}"; string arguments = string.Format(format, appid); Process process = Process.Start("xdg-mime", arguments); process.WaitForExit(); return process.ExitCode >= 0; } } internal class UriSchemeRegister { private ILogger _logger; public string ApplicationID { get; set; } public string SteamAppID { get; set; } public bool UsingSteamApp => !string.IsNullOrEmpty(SteamAppID) && SteamAppID != ""; public string ExecutablePath { get; set; } public UriSchemeRegister(ILogger logger, string applicationID, string steamAppID = null, string executable = null) { _logger = logger; ApplicationID = applicationID.Trim(); SteamAppID = steamAppID?.Trim(); ExecutablePath = executable ?? GetApplicationLocation(); } public bool RegisterUriScheme() { IUriSchemeCreator uriSchemeCreator = null; switch (Environment.OSVersion.Platform) { case PlatformID.Win32S: case PlatformID.Win32Windows: case PlatformID.Win32NT: case PlatformID.WinCE: _logger.Trace("Creating Windows Scheme Creator"); uriSchemeCreator = new WindowsUriSchemeCreator(_logger); break; case PlatformID.Unix: _logger.Trace("Creating Unix Scheme Creator"); uriSchemeCreator = new UnixUriSchemeCreator(_logger); break; case PlatformID.MacOSX: _logger.Trace("Creating MacOSX Scheme Creator"); uriSchemeCreator = new MacUriSchemeCreator(_logger); break; default: _logger.Error("Unkown Platform: " + Environment.OSVersion.Platform); throw new PlatformNotSupportedException("Platform does not support registration."); } if (uriSchemeCreator.RegisterUriScheme(this)) { _logger.Info("URI scheme registered."); return true; } return false; } public static string GetApplicationLocation() { return Process.GetCurrentProcess().MainModule.FileName; } } internal class WindowsUriSchemeCreator : IUriSchemeCreator { private ILogger logger; public WindowsUriSchemeCreator(ILogger logger) { this.logger = logger; } public bool RegisterUriScheme(UriSchemeRegister register) { if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX) { throw new PlatformNotSupportedException("URI schemes can only be registered on Windows"); } string executablePath = register.ExecutablePath; if (executablePath == null) { logger.Error("Failed to register application because the location was null."); return false; } string scheme = "discord-" + register.ApplicationID; string friendlyName = "Run game " + register.ApplicationID + " protocol"; string defaultIcon = executablePath; string command = executablePath; if (register.UsingSteamApp) { string steamLocation = GetSteamLocation(); if (steamLocation != null) { command = $"\"{steamLocation}\" steam://rungameid/{register.SteamAppID}"; } } CreateUriScheme(scheme, friendlyName, defaultIcon, command); return true; } private void CreateUriScheme(string scheme, string friendlyName, string defaultIcon, string command) { using (RegistryKey registryKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey("SOFTWARE\\Classes\\" + scheme)) { registryKey.SetValue("", "URL:" + friendlyName); registryKey.SetValue("URL Protocol", ""); using (RegistryKey registryKey2 = registryKey.CreateSubKey("DefaultIcon")) { registryKey2.SetValue("", defaultIcon); } using RegistryKey registryKey3 = registryKey.CreateSubKey("shell\\open\\command"); registryKey3.SetValue("", command); } logger.Trace("Registered {0}, {1}, {2}", scheme, friendlyName, command); } public string GetSteamLocation() { using RegistryKey registryKey = Microsoft.Win32.Registry.CurrentUser.OpenSubKey("Software\\Valve\\Steam"); if (registryKey == null) { return null; } return registryKey.GetValue("SteamExe") as string; } } } namespace DiscordRPC.Message { public class CloseMessage : IMessage { public override MessageType Type => MessageType.Close; public string Reason { get; internal set; } public int Code { get; internal set; } internal CloseMessage() { } internal CloseMessage(string reason) { Reason = reason; } } public class ConnectionEstablishedMessage : IMessage { public override MessageType Type => MessageType.ConnectionEstablished; public int ConnectedPipe { get; internal set; } } public class ConnectionFailedMessage : IMessage { public override MessageType Type => MessageType.ConnectionFailed; public int FailedPipe { get; internal set; } } public class ErrorMessage : IMessage { public override MessageType Type => MessageType.Error; [JsonProperty("code")] public ErrorCode Code { get; internal set; } [JsonProperty("message")] public string Message { get; internal set; } } public enum ErrorCode { Success = 0, PipeException = 1, ReadCorrupt = 2, NotImplemented = 10, UnkownError = 1000, InvalidPayload = 4000, InvalidCommand = 4002, InvalidEvent = 4004 } public abstract class IMessage { private DateTime _timecreated; public abstract MessageType Type { get; } public DateTime TimeCreated => _timecreated; public IMessage() { _timecreated = DateTime.Now; } } public class JoinMessage : IMessage { public override MessageType Type => MessageType.Join; [JsonProperty("secret")] public string Secret { get; internal set; } } public class JoinRequestMessage : IMessage { public override MessageType Type => MessageType.JoinRequest; [JsonProperty("user")] public User User { get; internal set; } } public enum MessageType { Ready, Close, Error, PresenceUpdate, Subscribe, Unsubscribe, Join, Spectate, JoinRequest, ConnectionEstablished, ConnectionFailed } public class PresenceMessage : IMessage { public override MessageType Type => MessageType.PresenceUpdate; public BaseRichPresence Presence { get; internal set; } public string Name { get; internal set; } public string ApplicationID { get; internal set; } internal PresenceMessage() : this(null) { } internal PresenceMessage(RichPresenceResponse rpr) { if (rpr == null) { Presence = null; Name = "No Rich Presence"; ApplicationID = ""; } else { Presence = rpr; Name = rpr.Name; ApplicationID = rpr.ClientID; } } } public class ReadyMessage : IMessage { public override MessageType Type => MessageType.Ready; [JsonProperty("config")] public Configuration Configuration { get; set; } [JsonProperty("user")] public User User { get; set; } [JsonProperty("v")] public int Version { get; set; } } public class SpectateMessage : JoinMessage { public override MessageType Type => MessageType.Spectate; } public class SubscribeMessage : IMessage { public override MessageType Type => MessageType.Subscribe; public EventType Event { get; internal set; } internal SubscribeMessage(ServerEvent evt) { switch (evt) { default: Event = EventType.Join; break; case ServerEvent.ActivityJoinRequest: Event = EventType.JoinRequest; break; case ServerEvent.ActivitySpectate: Event = EventType.Spectate; break; } } } public class UnsubscribeMessage : IMessage { public override MessageType Type => MessageType.Unsubscribe; public EventType Event { get; internal set; } internal UnsubscribeMessage(ServerEvent evt) { switch (evt) { default: Event = EventType.Join; break; case ServerEvent.ActivityJoinRequest: Event = EventType.JoinRequest; break; case ServerEvent.ActivitySpectate: Event = EventType.Spectate; break; } } } } namespace DiscordRPC.Logging { public class ConsoleLogger : ILogger { public LogLevel Level { get; set; } public bool Coloured { get; set; } public bool Colored { get { return Coloured; } set { Coloured = value; } } public ConsoleLogger() { Level = LogLevel.Info; Coloured = false; } public ConsoleLogger(LogLevel level, bool coloured = false) { Level = level; Coloured = coloured; } public void Trace(string message, params object[] args) { if (Level <= LogLevel.Trace) { if (Coloured) { Console.ForegroundColor = ConsoleColor.Gray; } Console.WriteLine("TRACE: " + message, args); } } public void Info(string message, params object[] args) { if (Level <= LogLevel.Info) { if (Coloured) { Console.ForegroundColor = ConsoleColor.White; } Console.WriteLine("INFO: " + message, args); } } public void Warning(string message, params object[] args) { if (Level <= LogLevel.Warning) { if (Coloured) { Console.ForegroundColor = ConsoleColor.Yellow; } Console.WriteLine("WARN: " + message, args); } } public void Error(string message, params object[] args) { if (Level <= LogLevel.Error) { if (Coloured) { Console.ForegroundColor = ConsoleColor.Red; } Console.WriteLine("ERR : " + message, args); } } } public class FileLogger : ILogger { private object filelock; public LogLevel Level { get; set; } public string File { get; set; } public FileLogger(string path) : this(path, LogLevel.Info) { } public FileLogger(string path, LogLevel level) { Level = level; File = path; filelock = new object(); } public void Trace(string message, params object[] args) { if (Level > LogLevel.Trace) { return; } lock (filelock) { System.IO.File.AppendAllText(File, "\r\nTRCE: " + ((args.Length != 0) ? string.Format(message, args) : message)); } } public void Info(string message, params object[] args) { if (Level > LogLevel.Info) { return; } lock (filelock) { System.IO.File.AppendAllText(File, "\r\nINFO: " + ((args.Length != 0) ? string.Format(message, args) : message)); } } public void Warning(string message, params object[] args) { if (Level > LogLevel.Warning) { return; } lock (filelock) { System.IO.File.AppendAllText(File, "\r\nWARN: " + ((args.Length != 0) ? string.Format(message, args) : message)); } } public void Error(string message, params object[] args) { if (Level > LogLevel.Error) { return; } lock (filelock) { System.IO.File.AppendAllText(File, "\r\nERR : " + ((args.Length != 0) ? string.Format(message, args) : message)); } } } public interface ILogger { LogLevel Level { get; set; } void Trace(string message, params object[] args); void Info(string message, params object[] args); void Warning(string message, params object[] args); void Error(string message, params object[] args); } public enum LogLevel { Trace = 1, Info = 2, Warning = 3, Error = 4, None = 256 } public class NullLogger : ILogger { public LogLevel Level { get; set; } public void Trace(string message, params object[] args) { } public void Info(string message, params object[] args) { } public void Warning(string message, params object[] args) { } public void Error(string message, params object[] args) { } } } namespace DiscordRPC.IO { internal class Handshake { [JsonProperty("v")] public int Version { get; set; } [JsonProperty("client_id")] public string ClientID { get; set; } } public interface INamedPipeClient : IDisposable { ILogger Logger { get; set; } bool IsConnected { get; } int ConnectedPipe { get; } bool Connect(int pipe); bool ReadFrame(out PipeFrame frame); bool WriteFrame(PipeFrame frame); void Close(); } public sealed class ManagedNamedPipeClient : INamedPipeClient, IDisposable { private const string PIPE_NAME = "discord-ipc-{0}"; private int _connectedPipe; private NamedPipeClientStream _stream; private byte[] _buffer = new byte[PipeFrame.MAX_SIZE]; private Queue<PipeFrame> _framequeue = new Queue<PipeFrame>(); private object _framequeuelock = new object(); private volatile bool _isDisposed = false; private volatile bool _isClosed = true; private object l_stream = new object(); public ILogger Logger { get; set; } public bool IsConnected { get { if (_isClosed) { return false; } lock (l_stream) { return _stream != null && _stream.IsConnected; } } } public int ConnectedPipe => _connectedPipe; public ManagedNamedPipeClient() { _buffer = new byte[PipeFrame.MAX_SIZE]; Logger = new NullLogger(); _stream = null; } public bool Connect(int pipe) { Logger.Trace("ManagedNamedPipeClient.Connection(" + pipe + ")"); if (_isDisposed) { throw new ObjectDisposedException("NamedPipe"); } if (pipe > 9) { throw new ArgumentOutOfRangeException("pipe", "Argument cannot be greater than 9"); } if (pipe < 0) { for (int i = 0; i < 10; i++) { if (AttemptConnection(i) || AttemptConnection(i, isSandbox: true)) { BeginReadStream(); return true; } } } else if (AttemptConnection(pipe) || AttemptConnection(pipe, isSandbox: true)) { BeginReadStream(); return true; } return false; } private bool AttemptConnection(int pipe, bool isSandbox = false) { if (_isDisposed) { throw new ObjectDisposedException("_stream"); } string text = (isSandbox ? GetPipeSandbox() : ""); if (isSandbox && text == null) { Logger.Trace("Skipping sandbox connection."); return false; } Logger.Trace("Connection Attempt " + pipe + " (" + text + ")"); string pipeName = GetPipeName(pipe, text); try { lock (l_stream) { Logger.Info("Attempting to connect to " + pipeName); _stream = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.Asynchronous); _stream.Connect(1000); Logger.Trace("Waiting for connection..."); do { Thread.Sleep(10); } while (!_stream.IsConnected); } Logger.Info("Connected to " + pipeName); _connectedPipe = pipe; _isClosed = false; } catch (Exception ex) { Logger.Error("Failed connection to {0}. {1}", pipeName, ex.Message); Close(); } Logger.Trace("Done. Result: {0}", _isClosed); return !_isClosed; } private void BeginReadStream() { if (_isClosed) { return; } try { lock (l_stream) { if (_stream != null && _stream.IsConnected) { Logger.Trace("Begining Read of {0} bytes", _buffer.Length); _stream.BeginRead(_buffer, 0, _buffer.Length, EndReadStream, _stream.IsConnected); } } } catch (ObjectDisposedException) { Logger.Warning("Attempted to start reading from a disposed pipe"); } catch (InvalidOperationException) { Logger.Warning("Attempted to start reading from a closed pipe"); } catch (Exception ex3) { Logger.Error("An exception occured while starting to read a stream: {0}", ex3.Message); Logger.Error(ex3.StackTrace); } } private void EndReadStream(IAsyncResult callback) { Logger.Trace("Ending Read"); int num = 0; try { lock (l_stream) { if (_stream == null || !_stream.IsConnected) { return; } num = _stream.EndRead(callback); } } catch (IOException) { Logger.Warning("Attempted to end reading from a closed pipe"); return; } catch (NullReferenceException) { Logger.Warning("Attempted to read from a null pipe"); return; } catch (ObjectDisposedException) { Logger.Warning("Attemped to end reading from a disposed pipe"); return; } catch (Exception ex4) { Logger.Error("An exception occured while ending a read of a stream: {0}", ex4.Message); Logger.Error(ex4.StackTrace); return; } Logger.Trace("Read {0} bytes", num); if (num > 0) { using MemoryStream stream = new MemoryStream(_buffer, 0, num); try { PipeFrame item = default(PipeFrame); if (item.ReadStream(stream)) { Logger.Trace("Read a frame: {0}", item.Opcode); lock (_framequeuelock) { _framequeue.Enqueue(item); } } else { Logger.Error("Pipe failed to read from the data received by the stream."); Close(); } } catch (Exception ex5) { Logger.Error("A exception has occured while trying to parse the pipe data: " + ex5.Message); Close(); } } else if (IsUnix()) { Logger.Error("Empty frame was read on " + Environment.OSVersion.ToString() + ", aborting."); Close(); } else { Logger.Warning("Empty frame was read. Please send report to Lachee."); } if (!_isClosed && IsConnected) { Logger.Trace("Starting another read"); BeginReadStream(); } } public bool ReadFrame(out PipeFrame frame) { if (_isDisposed) { throw new ObjectDisposedException("_stream"); } lock (_framequeuelock) { if (_framequeue.Count == 0) { frame = default(PipeFrame); return false; } frame = _framequeue.Dequeue(); return true; } } public bool WriteFrame(PipeFrame frame) { if (_isDisposed) { throw new ObjectDisposedException("_stream"); } if (_isClosed || !IsConnected) { Logger.Error("Failed to write frame because the stream is closed"); return false; } try { frame.WriteStream(_stream); return true; } catch (IOException ex) { Logger.Error("Failed to write frame because of a IO Exception: {0}", ex.Message); } catch (ObjectDisposedException) { Logger.Warning("Failed to write frame as the stream was already disposed"); } catch (InvalidOperationException) { Logger.Warning("Failed to write frame because of a invalid operation"); } return false; } public void Close() { if (_isClosed) { Logger.Warning("Tried to close a already closed pipe."); return; } try { lock (l_stream) { if (_stream != null) { try { _stream.Flush(); _stream.Dispose(); } catch (Exception) { } _stream = null; _isClosed = true; } else { Logger.Warning("Stream was closed, but no stream was available to begin with!"); } } } catch (ObjectDisposedException) { Logger.Warning("Tried to dispose already disposed stream"); } finally { _isClosed = true; _connectedPipe = -1; } } public void Dispose() { if (_isDisposed) { return; } if (!_isClosed) { Close(); } lock (l_stream) { if (_stream != null) { _stream.Dispose(); _stream = null; } } _isDisposed = true; } public static string GetPipeName(int pipe, string sandbox = "") { if (!IsUnix()) { return sandbox + $"discord-ipc-{pipe}"; } return Path.Combine(GetTemporaryDirectory(), sandbox + $"discord-ipc-{pipe}"); } public static string GetPipeSandbox() { PlatformID platform = Environment.OSVersion.Platform; PlatformID platformID = platform; if (platformID != PlatformID.Unix) { return null; } return "snap.discord/"; } private static string GetTemporaryDirectory() { string text = null; text = text ?? Environment.GetEnvironmentVariable("XDG_RUNTIME_DIR"); text = text ?? Environment.GetEnvironmentVariable("TMPDIR"); text = text ?? Environment.GetEnvironmentVariable("TMP"); text = text ?? Environment.GetEnvironmentVariable("TEMP"); return text ?? "/tmp"; } public static bool IsUnix() { PlatformID platform = Environment.OSVersion.Platform; PlatformID platformID = platform; if (platformID != PlatformID.Unix && platformID != PlatformID.MacOSX) { return false; } return true; } } public enum Opcode : uint { Handshake, Frame, Close, Ping, Pong } public struct PipeFrame { public static readonly int MAX_SIZE = 16384; public Opcode Opcode { get; set; } public uint Length => (uint)Data.Length; public byte[] Data { get; set; } public string Message { get { return GetMessage(); } set { SetMessage(value); } } public Encoding MessageEncoding => Encoding.UTF8; public PipeFrame(Opcode opcode, object data) { Opcode = opcode; Data = null; SetObject(data); } private void SetMessage(string str) { Data = MessageEncoding.GetBytes(str); } private string GetMessage() { return MessageEncoding.GetString(Data); } public void SetObject(object obj) { string message = JsonConvert.SerializeObject(obj); SetMessage(message); } public void SetObject(Opcode opcode, object obj) { Opcode = opcode; SetObject(obj); } public T GetObject<T>() { string message = GetMessage(); return JsonConvert.DeserializeObject<T>(message); } public bool ReadStream(Stream stream) { if (!TryReadUInt32(stream, out var value)) { return false; } if (!TryReadUInt32(stream, out var value2)) { return false; } uint num = value2; using MemoryStream memoryStream = new MemoryStream(); byte[] array = new byte[Min(2048, value2)]; int count; while ((count = stream.Read(array, 0, Min(array.Length, num))) > 0) { num -= value2; memoryStream.Write(array, 0, count); } byte[] array2 = memoryStream.ToArray(); if (array2.LongLength != value2) { return false; } Opcode = (Opcode)value; Data = array2; return true; } private int Min(int a, uint b) { if (b >= a) { return a; } return (int)b; } private bool TryReadUInt32(Stream stream, out uint value) { byte[] array = new byte[4]; int num = stream.Read(array, 0, array.Length); if (num != 4) { value = 0u; return false; } value = BitConverter.ToUInt32(array, 0); return true; } public void WriteStream(Stream stream) { byte[] bytes = BitConverter.GetBytes((uint)Opcode); byte[] bytes2 = BitConverter.GetBytes(Length); byte[] array = new byte[bytes.Length + bytes2.Length + Data.Length]; bytes.CopyTo(array, 0); bytes2.CopyTo(array, bytes.Length); Data.CopyTo(array, bytes.Length + bytes2.Length); stream.Write(array, 0, array.Length); } } } namespace DiscordRPC.Helper { internal class BackoffDelay { private int _current; private int _fails; public int Maximum { get; private set; } public int Minimum { get; private set; } public int Current => _current; public int Fails => _fails; public Random Random { get; set; } private BackoffDelay() { } public BackoffDelay(int min, int max) : this(min, max, new Random()) { } public BackoffDelay(int min, int max, Random random) { Minimum = min; Maximum = max; _current = min; _fails = 0; Random = random; } public void Reset() { _fails = 0; _current = Minimum; } public int NextDelay() { _fails++; double num = (float)(Maximum - Minimum) / 100f; _current = (int)Math.Floor(num * (double)_fails) + Minimum; return Math.Min(Math.Max(_current, Minimum), Maximum); } } public static class StringTools { public static string GetNullOrString(this string str) { return (str.Length == 0 || string.IsNullOrEmpty(str.Trim())) ? null : str; } public static bool WithinLength(this string str, int bytes) { return str.WithinLength(bytes, Encoding.UTF8); } public static bool WithinLength(this string str, int bytes, Encoding encoding) { return encoding.GetByteCount(str) <= bytes; } public static string ToCamelCase(this string str) { return (from s in str?.ToLower().Split(new string[2] { "_", " " }, StringSplitOptions.RemoveEmptyEntries) select char.ToUpper(s[0]) + s.Substring(1, s.Length - 1)).Aggregate(string.Empty, (string s1, string s2) => s1 + s2); } public static string ToSnakeCase(this string str) { if (str == null) { return null; } string text = string.Concat(str.Select((char x, int i) => (i > 0 && char.IsUpper(x)) ? ("_" + x) : x.ToString()).ToArray()); return text.ToUpper(); } } } namespace DiscordRPC.Exceptions { public class BadPresenceException : Exception { internal BadPresenceException(string message) : base(message) { } } public class InvalidConfigurationException : Exception { internal InvalidConfigurationException(string message) : base(message) { } } [Obsolete("Not actually used anywhere")] public class InvalidPipeException : Exception { internal InvalidPipeException(string message) : base(message) { } } public class StringOutOfRangeException : Exception { public int MaximumLength { get; private set; } public int MinimumLength { get; private set; } internal StringOutOfRangeException(string message, int min, int max) : base(message) { MinimumLength = min; MaximumLength = max; } internal StringOutOfRangeException(int minumum, int max) : this("Length of string is out of range. Expected a value between " + minumum + " and " + max, minumum, max) { } internal StringOutOfRangeException(int max) : this("Length of string is out of range. Expected a value with a maximum length of " + max, 0, max) { } } public class UninitializedException : Exception { internal UninitializedException(string message) : base(message) { } internal UninitializedException() : this("Cannot perform action because the client has not been initialized yet or has been deinitialized.") { } } } namespace DiscordRPC.Events { public delegate void OnReadyEvent(object sender, ReadyMessage args); public delegate void OnCloseEvent(object sender, CloseMessage args); public delegate void OnErrorEvent(object sender, ErrorMessage args); public delegate void OnPresenceUpdateEvent(object sender, PresenceMessage args); public delegate void OnSubscribeEvent(object sender, SubscribeMessage args); public delegate void OnUnsubscribeEvent(object sender, UnsubscribeMessage args); public delegate void OnJoinEvent(object sender, JoinMessage args); public delegate void OnSpectateEvent(object sender, SpectateMessage args); public delegate void OnJoinRequestedEvent(object sender, JoinRequestMessage args); public delegate void OnConnectionEstablishedEvent(object sender, ConnectionEstablishedMessage args); public delegate void OnConnectionFailedEvent(object sender, ConnectionFailedMessage args); public delegate void OnRpcMessageEvent(object sender, IMessage msg); } namespace DiscordRPC.Converters { internal class EnumSnakeCaseConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType.IsEnum; } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { if (reader.Value == null) { return null; } object obj = null; if (TryParseEnum(objectType, (string)reader.Value, out obj)) { return obj; } return existingValue; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { Type type = value.GetType(); string text = Enum.GetName(type, value); MemberInfo[] members = type.GetMembers(BindingFlags.Static | BindingFlags.Public); MemberInfo[] array = members; foreach (MemberInfo memberInfo in array) { if (memberInfo.Name.Equals(text)) { object[] customAttributes = memberInfo.GetCustomAttributes(typeof(EnumValueAttribute), inherit: true); if (customAttributes.Length != 0) { text = ((EnumValueAttribute)customAttributes[0]).Value; } } } writer.WriteValue(text); } public bool TryParseEnum(Type enumType, string str, out object obj) { if (str == null) { obj = null; return false; } Type type = enumType; if (type.IsGenericType && (object)type.GetGenericTypeDefinition() == typeof(Nullable<>)) { type = type.GetGenericArguments().First(); } if (!type.IsEnum) { obj = null; return false; } MemberInfo[] members = type.GetMembers(BindingFlags.Static | BindingFlags.Public); MemberInfo[] array = members; foreach (MemberInfo memberInfo in array) { object[] customAttributes = memberInfo.GetCustomAttributes(typeof(EnumValueAttribute), inherit: true); object[] array2 = customAttributes; foreach (object obj2 in array2) { EnumValueAttribute enumValueAttribute = (EnumValueAttribute)obj2; if (str.Equals(enumValueAttribute.Value)) { obj = Enum.Parse(type, memberInfo.Name, ignoreCase: true); return true; } } } obj = null; return false; } } internal class EnumValueAttribute : Attribute { public string Value { get; set; } public EnumValueAttribute(string value) { Value = value; } } }
Cuno-DiscordRichPresence-1.2.1/Newtonsoft.Json.dll
Decompiled 2 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Collections.Specialized; using System.ComponentModel; using System.Data; using System.Data.SqlTypes; using System.Diagnostics; using System.Dynamic; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Numerics; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Runtime.Serialization.Formatters; using System.Runtime.Versioning; using System.Security; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Xml; using System.Xml.Linq; using Microsoft.CodeAnalysis; using Newtonsoft.Json.Bson; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq.JsonPath; using Newtonsoft.Json.Schema; using Newtonsoft.Json.Serialization; using Newtonsoft.Json.Utilities; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AllowPartiallyTrustedCallers] [assembly: InternalsVisibleTo("Newtonsoft.Json.Schema, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")] [assembly: InternalsVisibleTo("Newtonsoft.Json.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100f561df277c6c0b497d629032b410cdcf286e537c054724f7ffa0164345f62b3e642029d7a80cc351918955328c4adc8a048823ef90b0cf38ea7db0d729caf2b633c3babe08b0310198c1081995c19029bc675193744eab9d7345b8a67258ec17d112cebdbbb2a281487dceeafb9d83aa930f32103fbe1d2911425bc5744002c7")] [assembly: InternalsVisibleTo("Newtonsoft.Json.Dynamic, PublicKey=0024000004800000940000000602000000240000525341310004000001000100cbd8d53b9d7de30f1f1278f636ec462cf9c254991291e66ebb157a885638a517887633b898ccbcf0d5c5ff7be85a6abe9e765d0ac7cd33c68dac67e7e64530e8222101109f154ab14a941c490ac155cd1d4fcba0fabb49016b4ef28593b015cab5937da31172f03f67d09edda404b88a60023f062ae71d0b2e4438b74cc11dc9")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("9ca358aa-317b-4925-8ada-4a29e943a363")] [assembly: CLSCompliant(true)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("Newtonsoft")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyCopyright("Copyright © James Newton-King 2008")] [assembly: AssemblyDescription("Json.NET is a popular high-performance JSON framework for .NET")] [assembly: AssemblyFileVersion("12.0.2.23222")] [assembly: AssemblyInformationalVersion("12.0.2+4ab34b0461fb595805d092a46a58f35f66c84d6a")] [assembly: AssemblyProduct("Json.NET")] [assembly: AssemblyTitle("Json.NET .NET Standard 2.0")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: AssemblyVersion("12.0.0.0")] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class IsReadOnlyAttribute : Attribute { } } namespace Newtonsoft.Json { public enum ConstructorHandling { Default, AllowNonPublicDefaultConstructor } public enum DateFormatHandling { IsoDateFormat, MicrosoftDateFormat } public enum DateParseHandling { None, DateTime, DateTimeOffset } public enum DateTimeZoneHandling { Local, Utc, Unspecified, RoundtripKind } public class DefaultJsonNameTable : JsonNameTable { private class Entry { internal readonly string Value; internal readonly int HashCode; internal Entry Next; internal Entry(string value, int hashCode, Entry next) { Value = value; HashCode = hashCode; Next = next; } } private static readonly int HashCodeRandomizer; private int _count; private Entry[] _entries; private int _mask = 31; static DefaultJsonNameTable() { HashCodeRandomizer = Environment.TickCount; } public DefaultJsonNameTable() { _entries = new Entry[_mask + 1]; } public override string Get(char[] key, int start, int length) { if (length == 0) { return string.Empty; } int num = length + HashCodeRandomizer; num += (num << 7) ^ key[start]; int num2 = start + length; for (int i = start + 1; i < num2; i++) { num += (num << 7) ^ key[i]; } num -= num >> 17; num -= num >> 11; num -= num >> 5; int num3 = num & _mask; for (Entry entry = _entries[num3]; entry != null; entry = entry.Next) { if (entry.HashCode == num && TextEquals(entry.Value, key, start, length)) { return entry.Value; } } return null; } public string Add(string key) { if (key == null) { throw new ArgumentNullException("key"); } int length = key.Length; if (length == 0) { return string.Empty; } int num = length + HashCodeRandomizer; for (int i = 0; i < key.Length; i++) { num += (num << 7) ^ key[i]; } num -= num >> 17; num -= num >> 11; num -= num >> 5; for (Entry entry = _entries[num & _mask]; entry != null; entry = entry.Next) { if (entry.HashCode == num && entry.Value.Equals(key, StringComparison.Ordinal)) { return entry.Value; } } return AddEntry(key, num); } private string AddEntry(string str, int hashCode) { int num = hashCode & _mask; Entry entry = new Entry(str, hashCode, _entries[num]); _entries[num] = entry; if (_count++ == _mask) { Grow(); } return entry.Value; } private void Grow() { Entry[] entries = _entries; int num = _mask * 2 + 1; Entry[] array = new Entry[num + 1]; for (int i = 0; i < entries.Length; i++) { Entry entry = entries[i]; while (entry != null) { int num2 = entry.HashCode & num; Entry next = entry.Next; entry.Next = array[num2]; array[num2] = entry; entry = next; } } _entries = array; _mask = num; } private static bool TextEquals(string str1, char[] str2, int str2Start, int str2Length) { if (str1.Length != str2Length) { return false; } for (int i = 0; i < str1.Length; i++) { if (str1[i] != str2[str2Start + i]) { return false; } } return true; } } [Flags] public enum DefaultValueHandling { Include = 0, Ignore = 1, Populate = 2, IgnoreAndPopulate = 3 } public enum FloatFormatHandling { String, Symbol, DefaultValue } public enum FloatParseHandling { Double, Decimal } public enum Formatting { None, Indented } public interface IArrayPool<T> { T[] Rent(int minimumLength); void Return(T[] array); } public interface IJsonLineInfo { int LineNumber { get; } int LinePosition { get; } bool HasLineInfo(); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonArrayAttribute : JsonContainerAttribute { private bool _allowNullItems; public bool AllowNullItems { get { return _allowNullItems; } set { _allowNullItems = value; } } public JsonArrayAttribute() { } public JsonArrayAttribute(bool allowNullItems) { _allowNullItems = allowNullItems; } public JsonArrayAttribute(string id) : base(id) { } } [AttributeUsage(AttributeTargets.Constructor, AllowMultiple = false)] public sealed class JsonConstructorAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public abstract class JsonContainerAttribute : Attribute { internal bool? _isReference; internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; private Type _namingStrategyType; private object[] _namingStrategyParameters; public string Id { get; set; } public string Title { get; set; } public string Description { get; set; } public Type ItemConverterType { get; set; } public object[] ItemConverterParameters { get; set; } public Type NamingStrategyType { get { return _namingStrategyType; } set { _namingStrategyType = value; NamingStrategyInstance = null; } } public object[] NamingStrategyParameters { get { return _namingStrategyParameters; } set { _namingStrategyParameters = value; NamingStrategyInstance = null; } } internal NamingStrategy NamingStrategyInstance { get; set; } public bool IsReference { get { return _isReference ?? false; } set { _isReference = value; } } public bool ItemIsReference { get { return _itemIsReference ?? false; } set { _itemIsReference = value; } } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling ?? ReferenceLoopHandling.Error; } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling ?? TypeNameHandling.None; } set { _itemTypeNameHandling = value; } } protected JsonContainerAttribute() { } protected JsonContainerAttribute(string id) { Id = id; } } public static class JsonConvert { public static readonly string True = "true"; public static readonly string False = "false"; public static readonly string Null = "null"; public static readonly string Undefined = "undefined"; public static readonly string PositiveInfinity = "Infinity"; public static readonly string NegativeInfinity = "-Infinity"; public static readonly string NaN = "NaN"; public static Func<JsonSerializerSettings> DefaultSettings { get; set; } public static string ToString(DateTime value) { return ToString(value, DateFormatHandling.IsoDateFormat, DateTimeZoneHandling.RoundtripKind); } public static string ToString(DateTime value, DateFormatHandling format, DateTimeZoneHandling timeZoneHandling) { DateTime value2 = DateTimeUtils.EnsureDateTime(value, timeZoneHandling); using StringWriter stringWriter = StringUtils.CreateStringWriter(64); stringWriter.Write('"'); DateTimeUtils.WriteDateTimeString(stringWriter, value2, format, null, CultureInfo.InvariantCulture); stringWriter.Write('"'); return stringWriter.ToString(); } public static string ToString(DateTimeOffset value) { return ToString(value, DateFormatHandling.IsoDateFormat); } public static string ToString(DateTimeOffset value, DateFormatHandling format) { using StringWriter stringWriter = StringUtils.CreateStringWriter(64); stringWriter.Write('"'); DateTimeUtils.WriteDateTimeOffsetString(stringWriter, value, format, null, CultureInfo.InvariantCulture); stringWriter.Write('"'); return stringWriter.ToString(); } public static string ToString(bool value) { if (!value) { return False; } return True; } public static string ToString(char value) { return ToString(char.ToString(value)); } public static string ToString(Enum value) { return value.ToString("D"); } public static string ToString(int value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(short value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(ushort value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(uint value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(long value) { return value.ToString(null, CultureInfo.InvariantCulture); } private static string ToStringInternal(BigInteger value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(ulong value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(float value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } internal static string ToString(float value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureFloatFormat(double value, string text, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { if (floatFormatHandling == FloatFormatHandling.Symbol || (!double.IsInfinity(value) && !double.IsNaN(value))) { return text; } if (floatFormatHandling == FloatFormatHandling.DefaultValue) { if (nullable) { return Null; } return "0.0"; } return quoteChar + text + quoteChar; } public static string ToString(double value) { return EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)); } internal static string ToString(double value, FloatFormatHandling floatFormatHandling, char quoteChar, bool nullable) { return EnsureFloatFormat(value, EnsureDecimalPlace(value, value.ToString("R", CultureInfo.InvariantCulture)), floatFormatHandling, quoteChar, nullable); } private static string EnsureDecimalPlace(double value, string text) { if (double.IsNaN(value) || double.IsInfinity(value) || text.IndexOf('.') != -1 || text.IndexOf('E') != -1 || text.IndexOf('e') != -1) { return text; } return text + ".0"; } private static string EnsureDecimalPlace(string text) { if (text.IndexOf('.') != -1) { return text; } return text + ".0"; } public static string ToString(byte value) { return value.ToString(null, CultureInfo.InvariantCulture); } [CLSCompliant(false)] public static string ToString(sbyte value) { return value.ToString(null, CultureInfo.InvariantCulture); } public static string ToString(decimal value) { return EnsureDecimalPlace(value.ToString(null, CultureInfo.InvariantCulture)); } public static string ToString(Guid value) { return ToString(value, '"'); } internal static string ToString(Guid value, char quoteChar) { string text = value.ToString("D", CultureInfo.InvariantCulture); string text2 = quoteChar.ToString(CultureInfo.InvariantCulture); return text2 + text + text2; } public static string ToString(TimeSpan value) { return ToString(value, '"'); } internal static string ToString(TimeSpan value, char quoteChar) { return ToString(value.ToString(), quoteChar); } public static string ToString(Uri value) { if (value == null) { return Null; } return ToString(value, '"'); } internal static string ToString(Uri value, char quoteChar) { return ToString(value.OriginalString, quoteChar); } public static string ToString(string value) { return ToString(value, '"'); } public static string ToString(string value, char delimiter) { return ToString(value, delimiter, StringEscapeHandling.Default); } public static string ToString(string value, char delimiter, StringEscapeHandling stringEscapeHandling) { if (delimiter != '"' && delimiter != '\'') { throw new ArgumentException("Delimiter must be a single or double quote.", "delimiter"); } return JavaScriptUtils.ToEscapedJavaScriptString(value, delimiter, appendDelimiters: true, stringEscapeHandling); } public static string ToString(object value) { if (value == null) { return Null; } return ConvertUtils.GetTypeCode(value.GetType()) switch { PrimitiveTypeCode.String => ToString((string)value), PrimitiveTypeCode.Char => ToString((char)value), PrimitiveTypeCode.Boolean => ToString((bool)value), PrimitiveTypeCode.SByte => ToString((sbyte)value), PrimitiveTypeCode.Int16 => ToString((short)value), PrimitiveTypeCode.UInt16 => ToString((ushort)value), PrimitiveTypeCode.Int32 => ToString((int)value), PrimitiveTypeCode.Byte => ToString((byte)value), PrimitiveTypeCode.UInt32 => ToString((uint)value), PrimitiveTypeCode.Int64 => ToString((long)value), PrimitiveTypeCode.UInt64 => ToString((ulong)value), PrimitiveTypeCode.Single => ToString((float)value), PrimitiveTypeCode.Double => ToString((double)value), PrimitiveTypeCode.DateTime => ToString((DateTime)value), PrimitiveTypeCode.Decimal => ToString((decimal)value), PrimitiveTypeCode.DBNull => Null, PrimitiveTypeCode.DateTimeOffset => ToString((DateTimeOffset)value), PrimitiveTypeCode.Guid => ToString((Guid)value), PrimitiveTypeCode.Uri => ToString((Uri)value), PrimitiveTypeCode.TimeSpan => ToString((TimeSpan)value), PrimitiveTypeCode.BigInteger => ToStringInternal((BigInteger)value), _ => throw new ArgumentException("Unsupported type: {0}. Use the JsonSerializer class to get the object's JSON representation.".FormatWith(CultureInfo.InvariantCulture, value.GetType())), }; } [DebuggerStepThrough] public static string SerializeObject(object value) { return SerializeObject(value, (Type)null, (JsonSerializerSettings)null); } [DebuggerStepThrough] public static string SerializeObject(object value, Formatting formatting) { return SerializeObject(value, formatting, (JsonSerializerSettings)null); } [DebuggerStepThrough] public static string SerializeObject(object value, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return SerializeObject(value, null, settings); } [DebuggerStepThrough] public static string SerializeObject(object value, Formatting formatting, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] public static string SerializeObject(object value, JsonSerializerSettings settings) { return SerializeObject(value, null, settings); } [DebuggerStepThrough] public static string SerializeObject(object value, Type type, JsonSerializerSettings settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); return SerializeObjectInternal(value, type, jsonSerializer); } [DebuggerStepThrough] public static string SerializeObject(object value, Formatting formatting, JsonSerializerSettings settings) { return SerializeObject(value, null, formatting, settings); } [DebuggerStepThrough] public static string SerializeObject(object value, Type type, Formatting formatting, JsonSerializerSettings settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); jsonSerializer.Formatting = formatting; return SerializeObjectInternal(value, type, jsonSerializer); } private static string SerializeObjectInternal(object value, Type type, JsonSerializer jsonSerializer) { StringWriter stringWriter = new StringWriter(new StringBuilder(256), CultureInfo.InvariantCulture); using (JsonTextWriter jsonTextWriter = new JsonTextWriter(stringWriter)) { jsonTextWriter.Formatting = jsonSerializer.Formatting; jsonSerializer.Serialize(jsonTextWriter, value, type); } return stringWriter.ToString(); } [DebuggerStepThrough] public static object DeserializeObject(string value) { return DeserializeObject(value, (Type)null, (JsonSerializerSettings)null); } [DebuggerStepThrough] public static object DeserializeObject(string value, JsonSerializerSettings settings) { return DeserializeObject(value, null, settings); } [DebuggerStepThrough] public static object DeserializeObject(string value, Type type) { return DeserializeObject(value, type, (JsonSerializerSettings)null); } [DebuggerStepThrough] public static T DeserializeObject<T>(string value) { return JsonConvert.DeserializeObject<T>(value, (JsonSerializerSettings)null); } [DebuggerStepThrough] public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject) { return DeserializeObject<T>(value); } [DebuggerStepThrough] public static T DeserializeAnonymousType<T>(string value, T anonymousTypeObject, JsonSerializerSettings settings) { return DeserializeObject<T>(value, settings); } [DebuggerStepThrough] public static T DeserializeObject<T>(string value, params JsonConverter[] converters) { return (T)DeserializeObject(value, typeof(T), converters); } [DebuggerStepThrough] public static T DeserializeObject<T>(string value, JsonSerializerSettings settings) { return (T)DeserializeObject(value, typeof(T), settings); } [DebuggerStepThrough] public static object DeserializeObject(string value, Type type, params JsonConverter[] converters) { JsonSerializerSettings settings = ((converters != null && converters.Length != 0) ? new JsonSerializerSettings { Converters = converters } : null); return DeserializeObject(value, type, settings); } public static object DeserializeObject(string value, Type type, JsonSerializerSettings settings) { ValidationUtils.ArgumentNotNull(value, "value"); JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); if (!jsonSerializer.IsCheckAdditionalContentSet()) { jsonSerializer.CheckAdditionalContent = true; } using JsonTextReader reader = new JsonTextReader(new StringReader(value)); return jsonSerializer.Deserialize(reader, type); } [DebuggerStepThrough] public static void PopulateObject(string value, object target) { PopulateObject(value, target, null); } public static void PopulateObject(string value, object target, JsonSerializerSettings settings) { JsonSerializer jsonSerializer = JsonSerializer.CreateDefault(settings); using JsonReader jsonReader = new JsonTextReader(new StringReader(value)); jsonSerializer.Populate(jsonReader, target); if (settings == null || !settings.CheckAdditionalContent) { return; } while (jsonReader.Read()) { if (jsonReader.TokenType != JsonToken.Comment) { throw JsonSerializationException.Create(jsonReader, "Additional text found in JSON string after finishing deserializing object."); } } } public static string SerializeXmlNode(XmlNode node) { return SerializeXmlNode(node, Formatting.None); } public static string SerializeXmlNode(XmlNode node, Formatting formatting) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); return SerializeObject(node, formatting, xmlNodeConverter); } public static string SerializeXmlNode(XmlNode node, Formatting formatting, bool omitRootObject) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter { OmitRootObject = omitRootObject }; return SerializeObject(node, formatting, xmlNodeConverter); } public static XmlDocument DeserializeXmlNode(string value) { return DeserializeXmlNode(value, null); } public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute: false); } public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXmlNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false); } public static XmlDocument DeserializeXmlNode(string value, string deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName; xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute; xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters; return (XmlDocument)DeserializeObject(value, typeof(XmlDocument), xmlNodeConverter); } public static string SerializeXNode(XObject node) { return SerializeXNode(node, Formatting.None); } public static string SerializeXNode(XObject node, Formatting formatting) { return SerializeXNode(node, formatting, omitRootObject: false); } public static string SerializeXNode(XObject node, Formatting formatting, bool omitRootObject) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter { OmitRootObject = omitRootObject }; return SerializeObject(node, formatting, xmlNodeConverter); } public static XDocument DeserializeXNode(string value) { return DeserializeXNode(value, null); } public static XDocument DeserializeXNode(string value, string deserializeRootElementName) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute: false); } public static XDocument DeserializeXNode(string value, string deserializeRootElementName, bool writeArrayAttribute) { return DeserializeXNode(value, deserializeRootElementName, writeArrayAttribute, encodeSpecialCharacters: false); } public static XDocument DeserializeXNode(string value, string deserializeRootElementName, bool writeArrayAttribute, bool encodeSpecialCharacters) { XmlNodeConverter xmlNodeConverter = new XmlNodeConverter(); xmlNodeConverter.DeserializeRootElementName = deserializeRootElementName; xmlNodeConverter.WriteArrayAttribute = writeArrayAttribute; xmlNodeConverter.EncodeSpecialCharacters = encodeSpecialCharacters; return (XDocument)DeserializeObject(value, typeof(XDocument), xmlNodeConverter); } } public abstract class JsonConverter { public virtual bool CanRead => true; public virtual bool CanWrite => true; public abstract void WriteJson(JsonWriter writer, object value, JsonSerializer serializer); public abstract object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer); public abstract bool CanConvert(Type objectType); } public abstract class JsonConverter<T> : JsonConverter { public sealed override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { if (!((value != null) ? (value is T) : ReflectionUtils.IsNullable(typeof(T)))) { throw new JsonSerializationException("Converter cannot write specified value to JSON. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } WriteJson(writer, (T)value, serializer); } public abstract void WriteJson(JsonWriter writer, T value, JsonSerializer serializer); public sealed override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { bool flag = existingValue == null; if (!flag && !(existingValue is T)) { throw new JsonSerializationException("Converter cannot read JSON with the specified existing value. {0} is required.".FormatWith(CultureInfo.InvariantCulture, typeof(T))); } return ReadJson(reader, objectType, flag ? default(T) : ((T)existingValue), !flag, serializer); } public abstract T ReadJson(JsonReader reader, Type objectType, T existingValue, bool hasExistingValue, JsonSerializer serializer); public sealed override bool CanConvert(Type objectType) { return typeof(T).IsAssignableFrom(objectType); } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Interface | AttributeTargets.Parameter, AllowMultiple = false)] public sealed class JsonConverterAttribute : Attribute { private readonly Type _converterType; public Type ConverterType => _converterType; public object[] ConverterParameters { get; } public JsonConverterAttribute(Type converterType) { if (converterType == null) { throw new ArgumentNullException("converterType"); } _converterType = converterType; } public JsonConverterAttribute(Type converterType, params object[] converterParameters) : this(converterType) { ConverterParameters = converterParameters; } } public class JsonConverterCollection : Collection<JsonConverter> { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonDictionaryAttribute : JsonContainerAttribute { public JsonDictionaryAttribute() { } public JsonDictionaryAttribute(string id) : base(id) { } } [Serializable] public class JsonException : Exception { public JsonException() { } public JsonException(string message) : base(message) { } public JsonException(string message, Exception innerException) : base(message, innerException) { } public JsonException(SerializationInfo info, StreamingContext context) : base(info, context) { } internal static JsonException Create(IJsonLineInfo lineInfo, string path, string message) { message = JsonPosition.FormatMessage(lineInfo, path, message); return new JsonException(message); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public class JsonExtensionDataAttribute : Attribute { public bool WriteData { get; set; } public bool ReadData { get; set; } public JsonExtensionDataAttribute() { WriteData = true; ReadData = true; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public sealed class JsonIgnoreAttribute : Attribute { } public abstract class JsonNameTable { public abstract string Get(char[] key, int start, int length); } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface, AllowMultiple = false)] public sealed class JsonObjectAttribute : JsonContainerAttribute { private MemberSerialization _memberSerialization; internal MissingMemberHandling? _missingMemberHandling; internal Required? _itemRequired; internal NullValueHandling? _itemNullValueHandling; public MemberSerialization MemberSerialization { get { return _memberSerialization; } set { _memberSerialization = value; } } public MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling ?? MissingMemberHandling.Ignore; } set { _missingMemberHandling = value; } } public NullValueHandling ItemNullValueHandling { get { return _itemNullValueHandling ?? NullValueHandling.Include; } set { _itemNullValueHandling = value; } } public Required ItemRequired { get { return _itemRequired ?? Required.Default; } set { _itemRequired = value; } } public JsonObjectAttribute() { } public JsonObjectAttribute(MemberSerialization memberSerialization) { MemberSerialization = memberSerialization; } public JsonObjectAttribute(string id) : base(id) { } } internal enum JsonContainerType { None, Object, Array, Constructor } internal struct JsonPosition { private static readonly char[] SpecialCharacters = new char[18] { '.', ' ', '\'', '/', '"', '[', ']', '(', ')', '\t', '\n', '\r', '\f', '\b', '\\', '\u0085', '\u2028', '\u2029' }; internal JsonContainerType Type; internal int Position; internal string PropertyName; internal bool HasIndex; public JsonPosition(JsonContainerType type) { Type = type; HasIndex = TypeHasIndex(type); Position = -1; PropertyName = null; } internal int CalculateLength() { switch (Type) { case JsonContainerType.Object: return PropertyName.Length + 5; case JsonContainerType.Array: case JsonContainerType.Constructor: return MathUtils.IntLength((ulong)Position) + 2; default: throw new ArgumentOutOfRangeException("Type"); } } internal void WriteTo(StringBuilder sb, ref StringWriter writer, ref char[] buffer) { switch (Type) { case JsonContainerType.Object: { string propertyName = PropertyName; if (propertyName.IndexOfAny(SpecialCharacters) != -1) { sb.Append("['"); if (writer == null) { writer = new StringWriter(sb); } JavaScriptUtils.WriteEscapedJavaScriptString(writer, propertyName, '\'', appendDelimiters: false, JavaScriptUtils.SingleQuoteCharEscapeFlags, StringEscapeHandling.Default, null, ref buffer); sb.Append("']"); } else { if (sb.Length > 0) { sb.Append('.'); } sb.Append(propertyName); } break; } case JsonContainerType.Array: case JsonContainerType.Constructor: sb.Append('['); sb.Append(Position); sb.Append(']'); break; } } internal static bool TypeHasIndex(JsonContainerType type) { if (type != JsonContainerType.Array) { return type == JsonContainerType.Constructor; } return true; } internal static string BuildPath(List<JsonPosition> positions, JsonPosition? currentPosition) { int num = 0; if (positions != null) { for (int i = 0; i < positions.Count; i++) { num += positions[i].CalculateLength(); } } if (currentPosition.HasValue) { num += currentPosition.GetValueOrDefault().CalculateLength(); } StringBuilder stringBuilder = new StringBuilder(num); StringWriter writer = null; char[] buffer = null; if (positions != null) { foreach (JsonPosition position in positions) { position.WriteTo(stringBuilder, ref writer, ref buffer); } } currentPosition?.WriteTo(stringBuilder, ref writer, ref buffer); return stringBuilder.ToString(); } internal static string FormatMessage(IJsonLineInfo lineInfo, string path, string message) { if (!message.EndsWith(Environment.NewLine, StringComparison.Ordinal)) { message = message.Trim(); if (!StringUtils.EndsWith(message, '.')) { message += "."; } message += " "; } message += "Path '{0}'".FormatWith(CultureInfo.InvariantCulture, path); if (lineInfo != null && lineInfo.HasLineInfo()) { message += ", line {0}, position {1}".FormatWith(CultureInfo.InvariantCulture, lineInfo.LineNumber, lineInfo.LinePosition); } message += "."; return message; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = false)] public sealed class JsonPropertyAttribute : Attribute { internal NullValueHandling? _nullValueHandling; internal DefaultValueHandling? _defaultValueHandling; internal ReferenceLoopHandling? _referenceLoopHandling; internal ObjectCreationHandling? _objectCreationHandling; internal TypeNameHandling? _typeNameHandling; internal bool? _isReference; internal int? _order; internal Required? _required; internal bool? _itemIsReference; internal ReferenceLoopHandling? _itemReferenceLoopHandling; internal TypeNameHandling? _itemTypeNameHandling; public Type ItemConverterType { get; set; } public object[] ItemConverterParameters { get; set; } public Type NamingStrategyType { get; set; } public object[] NamingStrategyParameters { get; set; } public NullValueHandling NullValueHandling { get { return _nullValueHandling ?? NullValueHandling.Include; } set { _nullValueHandling = value; } } public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling ?? DefaultValueHandling.Include; } set { _defaultValueHandling = value; } } public ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling ?? ReferenceLoopHandling.Error; } set { _referenceLoopHandling = value; } } public ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling ?? ObjectCreationHandling.Auto; } set { _objectCreationHandling = value; } } public TypeNameHandling TypeNameHandling { get { return _typeNameHandling ?? TypeNameHandling.None; } set { _typeNameHandling = value; } } public bool IsReference { get { return _isReference ?? false; } set { _isReference = value; } } public int Order { get { return _order ?? 0; } set { _order = value; } } public Required Required { get { return _required ?? Required.Default; } set { _required = value; } } public string PropertyName { get; set; } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling ?? ReferenceLoopHandling.Error; } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling ?? TypeNameHandling.None; } set { _itemTypeNameHandling = value; } } public bool ItemIsReference { get { return _itemIsReference ?? false; } set { _itemIsReference = value; } } public JsonPropertyAttribute() { } public JsonPropertyAttribute(string propertyName) { PropertyName = propertyName; } } public abstract class JsonReader : IDisposable { protected internal enum State { Start, Complete, Property, ObjectStart, Object, ArrayStart, Array, Closed, PostValue, ConstructorStart, Constructor, Error, Finished } private JsonToken _tokenType; private object _value; internal char _quoteChar; internal State _currentState; private JsonPosition _currentPosition; private CultureInfo _culture; private DateTimeZoneHandling _dateTimeZoneHandling; private int? _maxDepth; private bool _hasExceededMaxDepth; internal DateParseHandling _dateParseHandling; internal FloatParseHandling _floatParseHandling; private string _dateFormatString; private List<JsonPosition> _stack; protected State CurrentState => _currentState; public bool CloseInput { get; set; } public bool SupportMultipleContent { get; set; } public virtual char QuoteChar { get { return _quoteChar; } protected internal set { _quoteChar = value; } } public DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling; } set { if (value < DateTimeZoneHandling.Local || value > DateTimeZoneHandling.RoundtripKind) { throw new ArgumentOutOfRangeException("value"); } _dateTimeZoneHandling = value; } } public DateParseHandling DateParseHandling { get { return _dateParseHandling; } set { if (value < DateParseHandling.None || value > DateParseHandling.DateTimeOffset) { throw new ArgumentOutOfRangeException("value"); } _dateParseHandling = value; } } public FloatParseHandling FloatParseHandling { get { return _floatParseHandling; } set { if (value < FloatParseHandling.Double || value > FloatParseHandling.Decimal) { throw new ArgumentOutOfRangeException("value"); } _floatParseHandling = value; } } public string DateFormatString { get { return _dateFormatString; } set { _dateFormatString = value; } } public int? MaxDepth { get { return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; } } public virtual JsonToken TokenType => _tokenType; public virtual object Value => _value; public virtual Type ValueType => _value?.GetType(); public virtual int Depth { get { int num = _stack?.Count ?? 0; if (JsonTokenUtils.IsStartToken(TokenType) || _currentPosition.Type == JsonContainerType.None) { return num; } return num + 1; } } public virtual string Path { get { if (_currentPosition.Type == JsonContainerType.None) { return string.Empty; } JsonPosition? currentPosition = ((_currentState != State.ArrayStart && _currentState != State.ConstructorStart && _currentState != State.ObjectStart) ? new JsonPosition?(_currentPosition) : null); return JsonPosition.BuildPath(_stack, currentPosition); } } public CultureInfo Culture { get { return _culture ?? CultureInfo.InvariantCulture; } set { _culture = value; } } public virtual Task<bool> ReadAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<bool>() ?? Read().ToAsync(); } public async Task SkipAsync(CancellationToken cancellationToken = default(CancellationToken)) { if (TokenType == JsonToken.PropertyName) { await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } if (JsonTokenUtils.IsStartToken(TokenType)) { int depth = Depth; while (await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false) && depth < Depth) { } } } internal async Task ReaderReadAndAssertAsync(CancellationToken cancellationToken) { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { throw CreateUnexpectedEndException(); } } public virtual Task<bool?> ReadAsBooleanAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<bool?>() ?? Task.FromResult(ReadAsBoolean()); } public virtual Task<byte[]> ReadAsBytesAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<byte[]>() ?? Task.FromResult(ReadAsBytes()); } internal async Task<byte[]> ReadArrayIntoByteArrayAsync(CancellationToken cancellationToken) { List<byte> buffer = new List<byte>(); do { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { SetToken(JsonToken.None); } } while (!ReadArrayElementIntoByteArrayReportDone(buffer)); byte[] array = buffer.ToArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } public virtual Task<DateTime?> ReadAsDateTimeAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<DateTime?>() ?? Task.FromResult(ReadAsDateTime()); } public virtual Task<DateTimeOffset?> ReadAsDateTimeOffsetAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<DateTimeOffset?>() ?? Task.FromResult(ReadAsDateTimeOffset()); } public virtual Task<decimal?> ReadAsDecimalAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<decimal?>() ?? Task.FromResult(ReadAsDecimal()); } public virtual Task<double?> ReadAsDoubleAsync(CancellationToken cancellationToken = default(CancellationToken)) { return Task.FromResult(ReadAsDouble()); } public virtual Task<int?> ReadAsInt32Async(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<int?>() ?? Task.FromResult(ReadAsInt32()); } public virtual Task<string> ReadAsStringAsync(CancellationToken cancellationToken = default(CancellationToken)) { return cancellationToken.CancelIfRequestedAsync<string>() ?? Task.FromResult(ReadAsString()); } internal async Task<bool> ReadAndMoveToContentAsync(CancellationToken cancellationToken) { bool flag = await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (flag) { flag = await MoveToContentAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } return flag; } internal Task<bool> MoveToContentAsync(CancellationToken cancellationToken) { JsonToken tokenType = TokenType; if (tokenType == JsonToken.None || tokenType == JsonToken.Comment) { return MoveToContentFromNonContentAsync(cancellationToken); } return AsyncUtils.True; } private async Task<bool> MoveToContentFromNonContentAsync(CancellationToken cancellationToken) { JsonToken tokenType; do { if (!(await ReadAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false))) { return false; } tokenType = TokenType; } while (tokenType == JsonToken.None || tokenType == JsonToken.Comment); return true; } internal JsonPosition GetPosition(int depth) { if (_stack != null && depth < _stack.Count) { return _stack[depth]; } return _currentPosition; } protected JsonReader() { _currentState = State.Start; _dateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; _dateParseHandling = DateParseHandling.DateTime; _floatParseHandling = FloatParseHandling.Double; CloseInput = true; } private void Push(JsonContainerType value) { UpdateScopeWithFinishedValue(); if (_currentPosition.Type == JsonContainerType.None) { _currentPosition = new JsonPosition(value); return; } if (_stack == null) { _stack = new List<JsonPosition>(); } _stack.Add(_currentPosition); _currentPosition = new JsonPosition(value); if (!_maxDepth.HasValue || !(Depth + 1 > _maxDepth) || _hasExceededMaxDepth) { return; } _hasExceededMaxDepth = true; throw JsonReaderException.Create(this, "The reader's MaxDepth of {0} has been exceeded.".FormatWith(CultureInfo.InvariantCulture, _maxDepth)); } private JsonContainerType Pop() { JsonPosition currentPosition; if (_stack != null && _stack.Count > 0) { currentPosition = _currentPosition; _currentPosition = _stack[_stack.Count - 1]; _stack.RemoveAt(_stack.Count - 1); } else { currentPosition = _currentPosition; _currentPosition = default(JsonPosition); } if (_maxDepth.HasValue && Depth <= _maxDepth) { _hasExceededMaxDepth = false; } return currentPosition.Type; } private JsonContainerType Peek() { return _currentPosition.Type; } public abstract bool Read(); public virtual int? ReadAsInt32() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; object obj; if ((obj = value) is int) { return (int)obj; } int num; if (value is BigInteger bigInteger) { num = (int)bigInteger; } else { try { num = Convert.ToInt32(value, CultureInfo.InvariantCulture); } catch (Exception ex) { throw JsonReaderException.Create(this, "Could not convert to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex); } } SetToken(JsonToken.Integer, num, updateIndex: false); return num; } case JsonToken.String: { string s = (string)Value; return ReadInt32String(s); } default: throw JsonReaderException.Create(this, "Error reading integer. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal int? ReadInt32String(string s) { if (string.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (int.TryParse(s, NumberStyles.Integer, Culture, out var result)) { SetToken(JsonToken.Integer, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to integer: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual string ReadAsString() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.String: return (string)Value; default: if (JsonTokenUtils.IsPrimitiveToken(contentToken)) { object value = Value; if (value != null) { string text = ((!(value is IFormattable formattable)) ? ((value is Uri uri) ? uri.OriginalString : value.ToString()) : formattable.ToString(null, Culture)); SetToken(JsonToken.String, text, updateIndex: false); return text; } } throw JsonReaderException.Create(this, "Error reading string. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } public virtual byte[] ReadAsBytes() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.StartObject: { ReadIntoWrappedTypeObject(); byte[] array2 = ReadAsBytes(); ReaderReadAndAssert(); if (TokenType != JsonToken.EndObject) { throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } SetToken(JsonToken.Bytes, array2, updateIndex: false); return array2; } case JsonToken.String: { string text = (string)Value; Guid g; byte[] array3 = ((text.Length == 0) ? CollectionUtils.ArrayEmpty<byte>() : ((!ConvertUtils.TryConvertGuid(text, out g)) ? Convert.FromBase64String(text) : g.ToByteArray())); SetToken(JsonToken.Bytes, array3, updateIndex: false); return array3; } case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Bytes: if (Value is Guid guid) { byte[] array = guid.ToByteArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } return (byte[])Value; case JsonToken.StartArray: return ReadArrayIntoByteArray(); default: throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal byte[] ReadArrayIntoByteArray() { List<byte> list = new List<byte>(); do { if (!Read()) { SetToken(JsonToken.None); } } while (!ReadArrayElementIntoByteArrayReportDone(list)); byte[] array = list.ToArray(); SetToken(JsonToken.Bytes, array, updateIndex: false); return array; } private bool ReadArrayElementIntoByteArrayReportDone(List<byte> buffer) { switch (TokenType) { case JsonToken.None: throw JsonReaderException.Create(this, "Unexpected end when reading bytes."); case JsonToken.Integer: buffer.Add(Convert.ToByte(Value, CultureInfo.InvariantCulture)); return false; case JsonToken.EndArray: return true; case JsonToken.Comment: return false; default: throw JsonReaderException.Create(this, "Unexpected token when reading bytes: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } public virtual double? ReadAsDouble() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; object obj; if ((obj = value) is double) { return (double)obj; } double num = ((!(value is BigInteger bigInteger)) ? Convert.ToDouble(value, CultureInfo.InvariantCulture) : ((double)bigInteger)); SetToken(JsonToken.Float, num, updateIndex: false); return num; } case JsonToken.String: return ReadDoubleString((string)Value); default: throw JsonReaderException.Create(this, "Error reading double. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal double? ReadDoubleString(string s) { if (string.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (double.TryParse(s, NumberStyles.Float | NumberStyles.AllowThousands, Culture, out var result)) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to double: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual bool? ReadAsBoolean() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { bool flag = ((!(Value is BigInteger bigInteger)) ? Convert.ToBoolean(Value, CultureInfo.InvariantCulture) : (bigInteger != 0L)); SetToken(JsonToken.Boolean, flag, updateIndex: false); return flag; } case JsonToken.String: return ReadBooleanString((string)Value); case JsonToken.Boolean: return (bool)Value; default: throw JsonReaderException.Create(this, "Error reading boolean. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal bool? ReadBooleanString(string s) { if (string.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (bool.TryParse(s, out var result)) { SetToken(JsonToken.Boolean, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to boolean: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual decimal? ReadAsDecimal() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Integer: case JsonToken.Float: { object value = Value; object obj; if ((obj = value) is decimal) { return (decimal)obj; } decimal num; if (value is BigInteger bigInteger) { num = (decimal)bigInteger; } else { try { num = Convert.ToDecimal(value, CultureInfo.InvariantCulture); } catch (Exception ex) { throw JsonReaderException.Create(this, "Could not convert to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, value), ex); } } SetToken(JsonToken.Float, num, updateIndex: false); return num; } case JsonToken.String: return ReadDecimalString((string)Value); default: throw JsonReaderException.Create(this, "Error reading decimal. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal decimal? ReadDecimalString(string s) { if (string.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (decimal.TryParse(s, NumberStyles.Number, Culture, out var result)) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } if (ConvertUtils.DecimalTryParse(s.ToCharArray(), 0, s.Length, out result) == ParseResult.Success) { SetToken(JsonToken.Float, result, updateIndex: false); return result; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to decimal: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual DateTime? ReadAsDateTime() { switch (GetContentToken()) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Date: if (Value is DateTimeOffset dateTimeOffset) { SetToken(JsonToken.Date, dateTimeOffset.DateTime, updateIndex: false); } return (DateTime)Value; case JsonToken.String: { string s = (string)Value; return ReadDateTimeString(s); } default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } internal DateTime? ReadDateTimeString(string s) { if (string.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (DateTimeUtils.TryParseDateTime(s, DateTimeZoneHandling, _dateFormatString, Culture, out var dt)) { dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } if (DateTime.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) { dt = DateTimeUtils.EnsureDateTime(dt, DateTimeZoneHandling); SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } throw JsonReaderException.Create(this, "Could not convert string to DateTime: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } public virtual DateTimeOffset? ReadAsDateTimeOffset() { JsonToken contentToken = GetContentToken(); switch (contentToken) { case JsonToken.None: case JsonToken.Null: case JsonToken.EndArray: return null; case JsonToken.Date: if (Value is DateTime dateTime) { SetToken(JsonToken.Date, new DateTimeOffset(dateTime), updateIndex: false); } return (DateTimeOffset)Value; case JsonToken.String: { string s = (string)Value; return ReadDateTimeOffsetString(s); } default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, contentToken)); } } internal DateTimeOffset? ReadDateTimeOffsetString(string s) { if (string.IsNullOrEmpty(s)) { SetToken(JsonToken.Null, null, updateIndex: false); return null; } if (DateTimeUtils.TryParseDateTimeOffset(s, _dateFormatString, Culture, out var dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } if (DateTimeOffset.TryParse(s, Culture, DateTimeStyles.RoundtripKind, out dt)) { SetToken(JsonToken.Date, dt, updateIndex: false); return dt; } SetToken(JsonToken.String, s, updateIndex: false); throw JsonReaderException.Create(this, "Could not convert string to DateTimeOffset: {0}.".FormatWith(CultureInfo.InvariantCulture, s)); } internal void ReaderReadAndAssert() { if (!Read()) { throw CreateUnexpectedEndException(); } } internal JsonReaderException CreateUnexpectedEndException() { return JsonReaderException.Create(this, "Unexpected end when reading JSON."); } internal void ReadIntoWrappedTypeObject() { ReaderReadAndAssert(); if (Value != null && Value.ToString() == "$type") { ReaderReadAndAssert(); if (Value != null && Value.ToString().StartsWith("System.Byte[]", StringComparison.Ordinal)) { ReaderReadAndAssert(); if (Value.ToString() == "$value") { return; } } } throw JsonReaderException.Create(this, "Error reading bytes. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, JsonToken.StartObject)); } public void Skip() { if (TokenType == JsonToken.PropertyName) { Read(); } if (JsonTokenUtils.IsStartToken(TokenType)) { int depth = Depth; while (Read() && depth < Depth) { } } } protected void SetToken(JsonToken newToken) { SetToken(newToken, null, updateIndex: true); } protected void SetToken(JsonToken newToken, object value) { SetToken(newToken, value, updateIndex: true); } protected void SetToken(JsonToken newToken, object value, bool updateIndex) { _tokenType = newToken; _value = value; switch (newToken) { case JsonToken.StartObject: _currentState = State.ObjectStart; Push(JsonContainerType.Object); break; case JsonToken.StartArray: _currentState = State.ArrayStart; Push(JsonContainerType.Array); break; case JsonToken.StartConstructor: _currentState = State.ConstructorStart; Push(JsonContainerType.Constructor); break; case JsonToken.EndObject: ValidateEnd(JsonToken.EndObject); break; case JsonToken.EndArray: ValidateEnd(JsonToken.EndArray); break; case JsonToken.EndConstructor: ValidateEnd(JsonToken.EndConstructor); break; case JsonToken.PropertyName: _currentState = State.Property; _currentPosition.PropertyName = (string)value; break; case JsonToken.Raw: case JsonToken.Integer: case JsonToken.Float: case JsonToken.String: case JsonToken.Boolean: case JsonToken.Null: case JsonToken.Undefined: case JsonToken.Date: case JsonToken.Bytes: SetPostValueState(updateIndex); break; case JsonToken.Comment: break; } } internal void SetPostValueState(bool updateIndex) { if (Peek() != 0 || SupportMultipleContent) { _currentState = State.PostValue; } else { SetFinished(); } if (updateIndex) { UpdateScopeWithFinishedValue(); } } private void UpdateScopeWithFinishedValue() { if (_currentPosition.HasIndex) { _currentPosition.Position++; } } private void ValidateEnd(JsonToken endToken) { JsonContainerType jsonContainerType = Pop(); if (GetTypeForCloseToken(endToken) != jsonContainerType) { throw JsonReaderException.Create(this, "JsonToken {0} is not valid for closing JsonType {1}.".FormatWith(CultureInfo.InvariantCulture, endToken, jsonContainerType)); } if (Peek() != 0 || SupportMultipleContent) { _currentState = State.PostValue; } else { SetFinished(); } } protected void SetStateBasedOnCurrent() { JsonContainerType jsonContainerType = Peek(); switch (jsonContainerType) { case JsonContainerType.Object: _currentState = State.Object; break; case JsonContainerType.Array: _currentState = State.Array; break; case JsonContainerType.Constructor: _currentState = State.Constructor; break; case JsonContainerType.None: SetFinished(); break; default: throw JsonReaderException.Create(this, "While setting the reader state back to current object an unexpected JsonType was encountered: {0}".FormatWith(CultureInfo.InvariantCulture, jsonContainerType)); } } private void SetFinished() { _currentState = ((!SupportMultipleContent) ? State.Finished : State.Start); } private JsonContainerType GetTypeForCloseToken(JsonToken token) { return token switch { JsonToken.EndObject => JsonContainerType.Object, JsonToken.EndArray => JsonContainerType.Array, JsonToken.EndConstructor => JsonContainerType.Constructor, _ => throw JsonReaderException.Create(this, "Not a valid close JsonToken: {0}".FormatWith(CultureInfo.InvariantCulture, token)), }; } void IDisposable.Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { if (_currentState != State.Closed && disposing) { Close(); } } public virtual void Close() { _currentState = State.Closed; _tokenType = JsonToken.None; _value = null; } internal void ReadAndAssert() { if (!Read()) { throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); } } internal void ReadForTypeAndAssert(JsonContract contract, bool hasConverter) { if (!ReadForType(contract, hasConverter)) { throw JsonSerializationException.Create(this, "Unexpected end when reading JSON."); } } internal bool ReadForType(JsonContract contract, bool hasConverter) { if (hasConverter) { return Read(); } switch (contract?.InternalReadType ?? ReadType.Read) { case ReadType.Read: return ReadAndMoveToContent(); case ReadType.ReadAsInt32: ReadAsInt32(); break; case ReadType.ReadAsInt64: { bool result = ReadAndMoveToContent(); if (TokenType == JsonToken.Undefined) { throw JsonReaderException.Create(this, "An undefined token is not a valid {0}.".FormatWith(CultureInfo.InvariantCulture, contract?.UnderlyingType ?? typeof(long))); } return result; } case ReadType.ReadAsDecimal: ReadAsDecimal(); break; case ReadType.ReadAsDouble: ReadAsDouble(); break; case ReadType.ReadAsBytes: ReadAsBytes(); break; case ReadType.ReadAsBoolean: ReadAsBoolean(); break; case ReadType.ReadAsString: ReadAsString(); break; case ReadType.ReadAsDateTime: ReadAsDateTime(); break; case ReadType.ReadAsDateTimeOffset: ReadAsDateTimeOffset(); break; default: throw new ArgumentOutOfRangeException(); } return TokenType != JsonToken.None; } internal bool ReadAndMoveToContent() { if (Read()) { return MoveToContent(); } return false; } internal bool MoveToContent() { JsonToken tokenType = TokenType; while (tokenType == JsonToken.None || tokenType == JsonToken.Comment) { if (!Read()) { return false; } tokenType = TokenType; } return true; } private JsonToken GetContentToken() { JsonToken tokenType; do { if (!Read()) { SetToken(JsonToken.None); return JsonToken.None; } tokenType = TokenType; } while (tokenType == JsonToken.Comment); return tokenType; } } [Serializable] public class JsonReaderException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string Path { get; } public JsonReaderException() { } public JsonReaderException(string message) : base(message) { } public JsonReaderException(string message, Exception innerException) : base(message, innerException) { } public JsonReaderException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonReaderException(string message, string path, int lineNumber, int linePosition, Exception innerException) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } internal static JsonReaderException Create(JsonReader reader, string message) { return Create(reader, message, null); } internal static JsonReaderException Create(JsonReader reader, string message, Exception ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } internal static JsonReaderException Create(IJsonLineInfo lineInfo, string path, string message, Exception ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); int lineNumber; int linePosition; if (lineInfo != null && lineInfo.HasLineInfo()) { lineNumber = lineInfo.LineNumber; linePosition = lineInfo.LinePosition; } else { lineNumber = 0; linePosition = 0; } return new JsonReaderException(message, path, lineNumber, linePosition, ex); } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = false)] public sealed class JsonRequiredAttribute : Attribute { } [Serializable] public class JsonSerializationException : JsonException { public int LineNumber { get; } public int LinePosition { get; } public string Path { get; } public JsonSerializationException() { } public JsonSerializationException(string message) : base(message) { } public JsonSerializationException(string message, Exception innerException) : base(message, innerException) { } public JsonSerializationException(SerializationInfo info, StreamingContext context) : base(info, context) { } public JsonSerializationException(string message, string path, int lineNumber, int linePosition, Exception innerException) : base(message, innerException) { Path = path; LineNumber = lineNumber; LinePosition = linePosition; } internal static JsonSerializationException Create(JsonReader reader, string message) { return Create(reader, message, null); } internal static JsonSerializationException Create(JsonReader reader, string message, Exception ex) { return Create(reader as IJsonLineInfo, reader.Path, message, ex); } internal static JsonSerializationException Create(IJsonLineInfo lineInfo, string path, string message, Exception ex) { message = JsonPosition.FormatMessage(lineInfo, path, message); int lineNumber; int linePosition; if (lineInfo != null && lineInfo.HasLineInfo()) { lineNumber = lineInfo.LineNumber; linePosition = lineInfo.LinePosition; } else { lineNumber = 0; linePosition = 0; } return new JsonSerializationException(message, path, lineNumber, linePosition, ex); } } public class JsonSerializer { internal TypeNameHandling _typeNameHandling; internal TypeNameAssemblyFormatHandling _typeNameAssemblyFormatHandling; internal PreserveReferencesHandling _preserveReferencesHandling; internal ReferenceLoopHandling _referenceLoopHandling; internal MissingMemberHandling _missingMemberHandling; internal ObjectCreationHandling _objectCreationHandling; internal NullValueHandling _nullValueHandling; internal DefaultValueHandling _defaultValueHandling; internal ConstructorHandling _constructorHandling; internal MetadataPropertyHandling _metadataPropertyHandling; internal JsonConverterCollection _converters; internal IContractResolver _contractResolver; internal ITraceWriter _traceWriter; internal IEqualityComparer _equalityComparer; internal ISerializationBinder _serializationBinder; internal StreamingContext _context; private IReferenceResolver _referenceResolver; private Formatting? _formatting; private DateFormatHandling? _dateFormatHandling; private DateTimeZoneHandling? _dateTimeZoneHandling; private DateParseHandling? _dateParseHandling; private FloatFormatHandling? _floatFormatHandling; private FloatParseHandling? _floatParseHandling; private StringEscapeHandling? _stringEscapeHandling; private CultureInfo _culture; private int? _maxDepth; private bool _maxDepthSet; private bool? _checkAdditionalContent; private string _dateFormatString; private bool _dateFormatStringSet; public virtual IReferenceResolver ReferenceResolver { get { return GetReferenceResolver(); } set { if (value == null) { throw new ArgumentNullException("value", "Reference resolver cannot be null."); } _referenceResolver = value; } } [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] public virtual SerializationBinder Binder { get { if (_serializationBinder == null) { return null; } if (_serializationBinder is SerializationBinder result) { return result; } if (_serializationBinder is SerializationBinderAdapter serializationBinderAdapter) { return serializationBinderAdapter.SerializationBinder; } throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set."); } set { if (value == null) { throw new ArgumentNullException("value", "Serialization binder cannot be null."); } _serializationBinder = (value as ISerializationBinder) ?? new SerializationBinderAdapter(value); } } public virtual ISerializationBinder SerializationBinder { get { return _serializationBinder; } set { if (value == null) { throw new ArgumentNullException("value", "Serialization binder cannot be null."); } _serializationBinder = value; } } public virtual ITraceWriter TraceWriter { get { return _traceWriter; } set { _traceWriter = value; } } public virtual IEqualityComparer EqualityComparer { get { return _equalityComparer; } set { _equalityComparer = value; } } public virtual TypeNameHandling TypeNameHandling { get { return _typeNameHandling; } set { if (value < TypeNameHandling.None || value > TypeNameHandling.Auto) { throw new ArgumentOutOfRangeException("value"); } _typeNameHandling = value; } } [Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")] public virtual FormatterAssemblyStyle TypeNameAssemblyFormat { get { return (FormatterAssemblyStyle)_typeNameAssemblyFormatHandling; } set { if (value < FormatterAssemblyStyle.Simple || value > FormatterAssemblyStyle.Full) { throw new ArgumentOutOfRangeException("value"); } _typeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value; } } public virtual TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling { get { return _typeNameAssemblyFormatHandling; } set { if (value < TypeNameAssemblyFormatHandling.Simple || value > TypeNameAssemblyFormatHandling.Full) { throw new ArgumentOutOfRangeException("value"); } _typeNameAssemblyFormatHandling = value; } } public virtual PreserveReferencesHandling PreserveReferencesHandling { get { return _preserveReferencesHandling; } set { if (value < PreserveReferencesHandling.None || value > PreserveReferencesHandling.All) { throw new ArgumentOutOfRangeException("value"); } _preserveReferencesHandling = value; } } public virtual ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling; } set { if (value < ReferenceLoopHandling.Error || value > ReferenceLoopHandling.Serialize) { throw new ArgumentOutOfRangeException("value"); } _referenceLoopHandling = value; } } public virtual MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling; } set { if (value < MissingMemberHandling.Ignore || value > MissingMemberHandling.Error) { throw new ArgumentOutOfRangeException("value"); } _missingMemberHandling = value; } } public virtual NullValueHandling NullValueHandling { get { return _nullValueHandling; } set { if (value < NullValueHandling.Include || value > NullValueHandling.Ignore) { throw new ArgumentOutOfRangeException("value"); } _nullValueHandling = value; } } public virtual DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling; } set { if (value < DefaultValueHandling.Include || value > DefaultValueHandling.IgnoreAndPopulate) { throw new ArgumentOutOfRangeException("value"); } _defaultValueHandling = value; } } public virtual ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling; } set { if (value < ObjectCreationHandling.Auto || value > ObjectCreationHandling.Replace) { throw new ArgumentOutOfRangeException("value"); } _objectCreationHandling = value; } } public virtual ConstructorHandling ConstructorHandling { get { return _constructorHandling; } set { if (value < ConstructorHandling.Default || value > ConstructorHandling.AllowNonPublicDefaultConstructor) { throw new ArgumentOutOfRangeException("value"); } _constructorHandling = value; } } public virtual MetadataPropertyHandling MetadataPropertyHandling { get { return _metadataPropertyHandling; } set { if (value < MetadataPropertyHandling.Default || value > MetadataPropertyHandling.Ignore) { throw new ArgumentOutOfRangeException("value"); } _metadataPropertyHandling = value; } } public virtual JsonConverterCollection Converters { get { if (_converters == null) { _converters = new JsonConverterCollection(); } return _converters; } } public virtual IContractResolver ContractResolver { get { return _contractResolver; } set { _contractResolver = value ?? DefaultContractResolver.Instance; } } public virtual StreamingContext Context { get { return _context; } set { _context = value; } } public virtual Formatting Formatting { get { return _formatting ?? Formatting.None; } set { _formatting = value; } } public virtual DateFormatHandling DateFormatHandling { get { return _dateFormatHandling ?? DateFormatHandling.IsoDateFormat; } set { _dateFormatHandling = value; } } public virtual DateTimeZoneHandling DateTimeZoneHandling { get { return _dateTimeZoneHandling ?? DateTimeZoneHandling.RoundtripKind; } set { _dateTimeZoneHandling = value; } } public virtual DateParseHandling DateParseHandling { get { return _dateParseHandling ?? DateParseHandling.DateTime; } set { _dateParseHandling = value; } } public virtual FloatParseHandling FloatParseHandling { get { return _floatParseHandling ?? FloatParseHandling.Double; } set { _floatParseHandling = value; } } public virtual FloatFormatHandling FloatFormatHandling { get { return _floatFormatHandling ?? FloatFormatHandling.String; } set { _floatFormatHandling = value; } } public virtual StringEscapeHandling StringEscapeHandling { get { return _stringEscapeHandling ?? StringEscapeHandling.Default; } set { _stringEscapeHandling = value; } } public virtual string DateFormatString { get { return _dateFormatString ?? "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; } set { _dateFormatString = value; _dateFormatStringSet = true; } } public virtual CultureInfo Culture { get { return _culture ?? JsonSerializerSettings.DefaultCulture; } set { _culture = value; } } public virtual int? MaxDepth { get { return _maxDepth; } set { if (value <= 0) { throw new ArgumentException("Value must be positive.", "value"); } _maxDepth = value; _maxDepthSet = true; } } public virtual bool CheckAdditionalContent { get { return _checkAdditionalContent ?? false; } set { _checkAdditionalContent = value; } } public virtual event EventHandler<Newtonsoft.Json.Serialization.ErrorEventArgs> Error; internal bool IsCheckAdditionalContentSet() { return _checkAdditionalContent.HasValue; } public JsonSerializer() { _referenceLoopHandling = ReferenceLoopHandling.Error; _missingMemberHandling = MissingMemberHandling.Ignore; _nullValueHandling = NullValueHandling.Include; _defaultValueHandling = DefaultValueHandling.Include; _objectCreationHandling = ObjectCreationHandling.Auto; _preserveReferencesHandling = PreserveReferencesHandling.None; _constructorHandling = ConstructorHandling.Default; _typeNameHandling = TypeNameHandling.None; _metadataPropertyHandling = MetadataPropertyHandling.Default; _context = JsonSerializerSettings.DefaultContext; _serializationBinder = DefaultSerializationBinder.Instance; _culture = JsonSerializerSettings.DefaultCulture; _contractResolver = DefaultContractResolver.Instance; } public static JsonSerializer Create() { return new JsonSerializer(); } public static JsonSerializer Create(JsonSerializerSettings settings) { JsonSerializer jsonSerializer = Create(); if (settings != null) { ApplySerializerSettings(jsonSerializer, settings); } return jsonSerializer; } public static JsonSerializer CreateDefault() { return Create(JsonConvert.DefaultSettings?.Invoke()); } public static JsonSerializer CreateDefault(JsonSerializerSettings settings) { JsonSerializer jsonSerializer = CreateDefault(); if (settings != null) { ApplySerializerSettings(jsonSerializer, settings); } return jsonSerializer; } private static void ApplySerializerSettings(JsonSerializer serializer, JsonSerializerSettings settings) { if (!CollectionUtils.IsNullOrEmpty(settings.Converters)) { for (int i = 0; i < settings.Converters.Count; i++) { serializer.Converters.Insert(i, settings.Converters[i]); } } if (settings._typeNameHandling.HasValue) { serializer.TypeNameHandling = settings.TypeNameHandling; } if (settings._metadataPropertyHandling.HasValue) { serializer.MetadataPropertyHandling = settings.MetadataPropertyHandling; } if (settings._typeNameAssemblyFormatHandling.HasValue) { serializer.TypeNameAssemblyFormatHandling = settings.TypeNameAssemblyFormatHandling; } if (settings._preserveReferencesHandling.HasValue) { serializer.PreserveReferencesHandling = settings.PreserveReferencesHandling; } if (settings._referenceLoopHandling.HasValue) { serializer.ReferenceLoopHandling = settings.ReferenceLoopHandling; } if (settings._missingMemberHandling.HasValue) { serializer.MissingMemberHandling = settings.MissingMemberHandling; } if (settings._objectCreationHandling.HasValue) { serializer.ObjectCreationHandling = settings.ObjectCreationHandling; } if (settings._nullValueHandling.HasValue) { serializer.NullValueHandling = settings.NullValueHandling; } if (settings._defaultValueHandling.HasValue) { serializer.DefaultValueHandling = settings.DefaultValueHandling; } if (settings._constructorHandling.HasValue) { serializer.ConstructorHandling = settings.ConstructorHandling; } if (settings._context.HasValue) { serializer.Context = settings.Context; } if (settings._checkAdditionalContent.HasValue) { serializer._checkAdditionalContent = settings._checkAdditionalContent; } if (settings.Error != null) { serializer.Error += settings.Error; } if (settings.ContractResolver != null) { serializer.ContractResolver = settings.ContractResolver; } if (settings.ReferenceResolverProvider != null) { serializer.ReferenceResolver = settings.ReferenceResolverProvider(); } if (settings.TraceWriter != null) { serializer.TraceWriter = settings.TraceWriter; } if (settings.EqualityComparer != null) { serializer.EqualityComparer = settings.EqualityComparer; } if (settings.SerializationBinder != null) { serializer.SerializationBinder = settings.SerializationBinder; } if (settings._formatting.HasValue) { serializer._formatting = settings._formatting; } if (settings._dateFormatHandling.HasValue) { serializer._dateFormatHandling = settings._dateFormatHandling; } if (settings._dateTimeZoneHandling.HasValue) { serializer._dateTimeZoneHandling = settings._dateTimeZoneHandling; } if (settings._dateParseHandling.HasValue) { serializer._dateParseHandling = settings._dateParseHandling; } if (settings._dateFormatStringSet) { serializer._dateFormatString = settings._dateFormatString; serializer._dateFormatStringSet = settings._dateFormatStringSet; } if (settings._floatFormatHandling.HasValue) { serializer._floatFormatHandling = settings._floatFormatHandling; } if (settings._floatParseHandling.HasValue) { serializer._floatParseHandling = settings._floatParseHandling; } if (settings._stringEscapeHandling.HasValue) { serializer._stringEscapeHandling = settings._stringEscapeHandling; } if (settings._culture != null) { serializer._culture = settings._culture; } if (settings._maxDepthSet) { serializer._maxDepth = settings._maxDepth; serializer._maxDepthSet = settings._maxDepthSet; } } [DebuggerStepThrough] public void Populate(TextReader reader, object target) { Populate(new JsonTextReader(reader), target); } [DebuggerStepThrough] public void Populate(JsonReader reader, object target) { PopulateInternal(reader, target); } internal virtual void PopulateInternal(JsonReader reader, object target) { ValidationUtils.ArgumentNotNull(reader, "reader"); ValidationUtils.ArgumentNotNull(target, "target"); SetupReader(reader, out var previousCulture, out var previousDateTimeZoneHandling, out var previousDateParseHandling, out var previousFloatParseHandling, out var previousMaxDepth, out var previousDateFormatString); TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null); new JsonSerializerInternalReader(this).Populate(traceJsonReader ?? reader, target); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); } [DebuggerStepThrough] public object Deserialize(JsonReader reader) { return Deserialize(reader, null); } [DebuggerStepThrough] public object Deserialize(TextReader reader, Type objectType) { return Deserialize(new JsonTextReader(reader), objectType); } [DebuggerStepThrough] public T Deserialize<T>(JsonReader reader) { return (T)Deserialize(reader, typeof(T)); } [DebuggerStepThrough] public object Deserialize(JsonReader reader, Type objectType) { return DeserializeInternal(reader, objectType); } internal virtual object DeserializeInternal(JsonReader reader, Type objectType) { ValidationUtils.ArgumentNotNull(reader, "reader"); SetupReader(reader, out var previousCulture, out var previousDateTimeZoneHandling, out var previousDateParseHandling, out var previousFloatParseHandling, out var previousMaxDepth, out var previousDateFormatString); TraceJsonReader traceJsonReader = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? CreateTraceJsonReader(reader) : null); object result = new JsonSerializerInternalReader(this).Deserialize(traceJsonReader ?? reader, objectType, CheckAdditionalContent); if (traceJsonReader != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonReader.GetDeserializedJsonMessage(), null); } ResetReader(reader, previousCulture, previousDateTimeZoneHandling, previousDateParseHandling, previousFloatParseHandling, previousMaxDepth, previousDateFormatString); return result; } private void SetupReader(JsonReader reader, out CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string previousDateFormatString) { if (_culture != null && !_culture.Equals(reader.Culture)) { previousCulture = reader.Culture; reader.Culture = _culture; } else { previousCulture = null; } if (_dateTimeZoneHandling.HasValue && reader.DateTimeZoneHandling != _dateTimeZoneHandling) { previousDateTimeZoneHandling = reader.DateTimeZoneHandling; reader.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault(); } else { previousDateTimeZoneHandling = null; } if (_dateParseHandling.HasValue && reader.DateParseHandling != _dateParseHandling) { previousDateParseHandling = reader.DateParseHandling; reader.DateParseHandling = _dateParseHandling.GetValueOrDefault(); } else { previousDateParseHandling = null; } if (_floatParseHandling.HasValue && reader.FloatParseHandling != _floatParseHandling) { previousFloatParseHandling = reader.FloatParseHandling; reader.FloatParseHandling = _floatParseHandling.GetValueOrDefault(); } else { previousFloatParseHandling = null; } if (_maxDepthSet && reader.MaxDepth != _maxDepth) { previousMaxDepth = reader.MaxDepth; reader.MaxDepth = _maxDepth; } else { previousMaxDepth = null; } if (_dateFormatStringSet && reader.DateFormatString != _dateFormatString) { previousDateFormatString = reader.DateFormatString; reader.DateFormatString = _dateFormatString; } else { previousDateFormatString = null; } if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable == null && _contractResolver is DefaultContractResolver defaultContractResolver) { jsonTextReader.PropertyNameTable = defaultContractResolver.GetNameTable(); } } private void ResetReader(JsonReader reader, CultureInfo previousCulture, DateTimeZoneHandling? previousDateTimeZoneHandling, DateParseHandling? previousDateParseHandling, FloatParseHandling? previousFloatParseHandling, int? previousMaxDepth, string previousDateFormatString) { if (previousCulture != null) { reader.Culture = previousCulture; } if (previousDateTimeZoneHandling.HasValue) { reader.DateTimeZoneHandling = previousDateTimeZoneHandling.GetValueOrDefault(); } if (previousDateParseHandling.HasValue) { reader.DateParseHandling = previousDateParseHandling.GetValueOrDefault(); } if (previousFloatParseHandling.HasValue) { reader.FloatParseHandling = previousFloatParseHandling.GetValueOrDefault(); } if (_maxDepthSet) { reader.MaxDepth = previousMaxDepth; } if (_dateFormatStringSet) { reader.DateFormatString = previousDateFormatString; } if (reader is JsonTextReader jsonTextReader && jsonTextReader.PropertyNameTable != null && _contractResolver is DefaultContractResolver defaultContractResolver && jsonTextReader.PropertyNameTable == defaultContractResolver.GetNameTable()) { jsonTextReader.PropertyNameTable = null; } } public void Serialize(TextWriter textWriter, object value) { Serialize(new JsonTextWriter(textWriter), value); } public void Serialize(JsonWriter jsonWriter, object value, Type objectType) { SerializeInternal(jsonWriter, value, objectType); } public void Serialize(TextWriter textWriter, object value, Type objectType) { Serialize(new JsonTextWriter(textWriter), value, objectType); } public void Serialize(JsonWriter jsonWriter, object value) { SerializeInternal(jsonWriter, value, null); } private TraceJsonReader CreateTraceJsonReader(JsonReader reader) { TraceJsonReader traceJsonReader = new TraceJsonReader(reader); if (reader.TokenType != 0) { traceJsonReader.WriteCurrentToken(); } return traceJsonReader; } internal virtual void SerializeInternal(JsonWriter jsonWriter, object value, Type objectType) { ValidationUtils.ArgumentNotNull(jsonWriter, "jsonWriter"); Formatting? formatting = null; if (_formatting.HasValue && jsonWriter.Formatting != _formatting) { formatting = jsonWriter.Formatting; jsonWriter.Formatting = _formatting.GetValueOrDefault(); } DateFormatHandling? dateFormatHandling = null; if (_dateFormatHandling.HasValue && jsonWriter.DateFormatHandling != _dateFormatHandling) { dateFormatHandling = jsonWriter.DateFormatHandling; jsonWriter.DateFormatHandling = _dateFormatHandling.GetValueOrDefault(); } DateTimeZoneHandling? dateTimeZoneHandling = null; if (_dateTimeZoneHandling.HasValue && jsonWriter.DateTimeZoneHandling != _dateTimeZoneHandling) { dateTimeZoneHandling = jsonWriter.DateTimeZoneHandling; jsonWriter.DateTimeZoneHandling = _dateTimeZoneHandling.GetValueOrDefault(); } FloatFormatHandling? floatFormatHandling = null; if (_floatFormatHandling.HasValue && jsonWriter.FloatFormatHandling != _floatFormatHandling) { floatFormatHandling = jsonWriter.FloatFormatHandling; jsonWriter.FloatFormatHandling = _floatFormatHandling.GetValueOrDefault(); } StringEscapeHandling? stringEscapeHandling = null; if (_stringEscapeHandling.HasValue && jsonWriter.StringEscapeHandling != _stringEscapeHandling) { stringEscapeHandling = jsonWriter.StringEscapeHandling; jsonWriter.StringEscapeHandling = _stringEscapeHandling.GetValueOrDefault(); } CultureInfo cultureInfo = null; if (_culture != null && !_culture.Equals(jsonWriter.Culture)) { cultureInfo = jsonWriter.Culture; jsonWriter.Culture = _culture; } string dateFormatString = null; if (_dateFormatStringSet && jsonWriter.DateFormatString != _dateFormatString) { dateFormatString = jsonWriter.DateFormatString; jsonWriter.DateFormatString = _dateFormatString; } TraceJsonWriter traceJsonWriter = ((TraceWriter != null && TraceWriter.LevelFilter >= TraceLevel.Verbose) ? new TraceJsonWriter(jsonWriter) : null); new JsonSerializerInternalWriter(this).Serialize(traceJsonWriter ?? jsonWriter, value, objectType); if (traceJsonWriter != null) { TraceWriter.Trace(TraceLevel.Verbose, traceJsonWriter.GetSerializedJsonMessage(), null); } if (formatting.HasValue) { jsonWriter.Formatting = formatting.GetValueOrDefault(); } if (dateFormatHandling.HasValue) { jsonWriter.DateFormatHandling = dateFormatHandling.GetValueOrDefault(); } if (dateTimeZoneHandling.HasValue) { jsonWriter.DateTimeZoneHandling = dateTimeZoneHandling.GetValueOrDefault(); } if (floatFormatHandling.HasValue) { jsonWriter.FloatFormatHandling = floatFormatHandling.GetValueOrDefault(); } if (stringEscapeHandling.HasValue) { jsonWriter.StringEscapeHandling = stringEscapeHandling.GetValueOrDefault(); } if (_dateFormatStringSet) { jsonWriter.DateFormatString = dateFormatString; } if (cultureInfo != null) { jsonWriter.Culture = cultureInfo; } } internal IReferenceResolver GetReferenceResolver() { if (_referenceResolver == null) { _referenceResolver = new DefaultReferenceResolver(); } return _referenceResolver; } internal JsonConverter GetMatchingConverter(Type type) { return GetMatchingConverter(_converters, type); } internal static JsonConverter GetMatchingConverter(IList<JsonConverter> converters, Type objectType) { if (converters != null) { for (int i = 0; i < converters.Count; i++) { JsonConverter jsonConverter = converters[i]; if (jsonConverter.CanConvert(objectType)) { return jsonConverter; } } } return null; } internal void OnError(Newtonsoft.Json.Serialization.ErrorEventArgs e) { this.Error?.Invoke(this, e); } } public class JsonSerializerSettings { internal const ReferenceLoopHandling DefaultReferenceLoopHandling = ReferenceLoopHandling.Error; internal const MissingMemberHandling DefaultMissingMemberHandling = MissingMemberHandling.Ignore; internal const NullValueHandling DefaultNullValueHandling = NullValueHandling.Include; internal const DefaultValueHandling DefaultDefaultValueHandling = DefaultValueHandling.Include; internal const ObjectCreationHandling DefaultObjectCreationHandling = ObjectCreationHandling.Auto; internal const PreserveReferencesHandling DefaultPreserveReferencesHandling = PreserveReferencesHandling.None; internal const ConstructorHandling DefaultConstructorHandling = ConstructorHandling.Default; internal const TypeNameHandling DefaultTypeNameHandling = TypeNameHandling.None; internal const MetadataPropertyHandling DefaultMetadataPropertyHandling = MetadataPropertyHandling.Default; internal static readonly StreamingContext DefaultContext; internal const Formatting DefaultFormatting = Formatting.None; internal const DateFormatHandling DefaultDateFormatHandling = DateFormatHandling.IsoDateFormat; internal const DateTimeZoneHandling DefaultDateTimeZoneHandling = DateTimeZoneHandling.RoundtripKind; internal const DateParseHandling DefaultDateParseHandling = DateParseHandling.DateTime; internal const FloatParseHandling DefaultFloatParseHandling = FloatParseHandling.Double; internal const FloatFormatHandling DefaultFloatFormatHandling = FloatFormatHandling.String; internal const StringEscapeHandling DefaultStringEscapeHandling = StringEscapeHandling.Default; internal const TypeNameAssemblyFormatHandling DefaultTypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple; internal static readonly CultureInfo DefaultCulture; internal const bool DefaultCheckAdditionalContent = false; internal const string DefaultDateFormatString = "yyyy'-'MM'-'dd'T'HH':'mm':'ss.FFFFFFFK"; internal Formatting? _formatting; internal DateFormatHandling? _dateFormatHandling; internal DateTimeZoneHandling? _dateTimeZoneHandling; internal DateParseHandling? _dateParseHandling; internal FloatFormatHandling? _floatFormatHandling; internal FloatParseHandling? _floatParseHandling; internal StringEscapeHandling? _stringEscapeHandling; internal CultureInfo _culture; internal bool? _checkAdditionalContent; internal int? _maxDepth; internal bool _maxDepthSet; internal string _dateFormatString; internal bool _dateFormatStringSet; internal TypeNameAssemblyFormatHandling? _typeNameAssemblyFormatHandling; internal DefaultValueHandling? _defaultValueHandling; internal PreserveReferencesHandling? _preserveReferencesHandling; internal NullValueHandling? _nullValueHandling; internal ObjectCreationHandling? _objectCreationHandling; internal MissingMemberHandling? _missingMemberHandling; internal ReferenceLoopHandling? _referenceLoopHandling; internal StreamingContext? _context; internal ConstructorHandling? _constructorHandling; internal TypeNameHandling? _typeNameHandling; internal MetadataPropertyHandling? _metadataPropertyHandling; public ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling ?? ReferenceLoopHandling.Error; } set { _referenceLoopHandling = value; } } public MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling ?? MissingMemberHandling.Ignore; } set { _missingMemberHandling = value; } } public ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling ?? ObjectCreationHandling.Auto; } set { _objectCreationHandling = value; } } public NullValueHandling NullValueHandling { get { return _nullValueHandling ?? NullValueHandling.Include; } set { _nullValueHandling = value; } } public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling ?? DefaultValueHandling.Include; } set { _defaultValueHandling = value; } } public IList<JsonConverter> Converters { get; set; } public PreserveReferencesHandling PreserveReferencesHandling { get { return _preserveReferencesHandling ?? PreserveReferencesHandling.None; } set { _preserveReferencesHandling = value; } } public TypeNameHandling TypeNameHandling { get { return _typeNameHandling ?? TypeNameHandling.None; } set { _typeNameHandling = value; } } public MetadataPropertyHandling MetadataPropertyHandling { get { return _metadataPropertyHandling ?? MetadataPropertyHandling.Default; } set { _metadataPropertyHandling = value; } } [Obsolete("TypeNameAssemblyFormat is obsolete. Use TypeNameAssemblyFormatHandling instead.")] public FormatterAssemblyStyle TypeNameAssemblyFormat { get { return (FormatterAssemblyStyle)TypeNameAssemblyFormatHandling; } set { TypeNameAssemblyFormatHandling = (TypeNameAssemblyFormatHandling)value; } } public TypeNameAssemblyFormatHandling TypeNameAssemblyFormatHandling { get { return _typeNameAssemblyFormatHandling ?? TypeNameAssemblyFormatHandling.Simple; } set { _typeNameAssemblyFormatHandling = value; } } public ConstructorHandling ConstructorHandling { get { return _constructorHandling ?? ConstructorHandling.Default; } set { _constructorHandling = value; } } public IContractResolver ContractResolver { get; set; } public IEqualityComparer EqualityComparer { get; set; } [Obsolete("ReferenceResolver property is obsolete. Use the ReferenceResolverProvider property to set the IReferenceResolver: settings.ReferenceResolverProvider = () => resolver")] public IReferenceResolver ReferenceResolver { get { return ReferenceResolverProvider?.Invoke(); } set { ReferenceResolverProvider = ((value != null) ? ((Func<IReferenceResolver>)(() => value)) : null); } } public Func<IReferenceResolver> ReferenceResolverProvider { get; set; } public ITraceWriter TraceWriter { get; set; } [Obsolete("Binder is obsolete. Use SerializationBinder instead.")] public SerializationBinder Binder { get { if (SerializationBinder == null) { return null; } if (SerializationBinder is SerializationBinderAdapter serializationBinderAdapter) { return serializationBinderAdapter.SerializationBinder; } throw new InvalidOperationException("Cannot get SerializationBinder because an ISerializationBinder was previously set."); } set { SerializationBinder = ((value == null) ? null : new SerializationBinderAdapter(value)); } } public ISerializationBinder SerializationBinder { get; set; } public EventHandler<Newtonsoft.Json.Serialization.ErrorEventArgs> Error { get; set; } public StreamingContext Context {
Cuno-DiscordRichPresence-1.2.1/UnityNamedPipe.dll
Decompiled 2 months agousing System; using System.Diagnostics; using System.IO; using System.IO.Pipes; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text; using System.Threading; using System.Threading.Tasks; using Lachee.IO.Exceptions; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = "")] [assembly: AssemblyCompany("UnityNamedPipe")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("UnityNamedPipe")] [assembly: AssemblyTitle("UnityNamedPipe")] [assembly: AssemblyVersion("1.0.0.0")] namespace Lachee.IO { public class NamedPipeClientStream : Stream { private static class Native { private const string LIBRARY_NAME = "NativeNamedPipe"; [DllImport("NativeNamedPipe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "createClient")] public static extern IntPtr CreateClient(); [DllImport("NativeNamedPipe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "destroyClient")] public static extern void DestroyClient(IntPtr client); [DllImport("NativeNamedPipe", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "isConnected")] public static extern bool IsConnected([MarshalAs(UnmanagedType.SysInt)] IntPtr client); [DllImport("NativeNamedPipe", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "open")] public static extern int Open(IntPtr client, [MarshalAs(UnmanagedType.LPStr)] string pipename); [DllImport("NativeNamedPipe", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Ansi, EntryPoint = "close")] public static extern void Close(IntPtr client); [DllImport("NativeNamedPipe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "readFrame")] public static extern int ReadFrame(IntPtr client, IntPtr buffer, int length); [DllImport("NativeNamedPipe", CallingConvention = CallingConvention.Cdecl, EntryPoint = "writeFrame")] public static extern int WriteFrame(IntPtr client, IntPtr buffer, int length); } private IntPtr ptr; private bool _isDisposed; private static readonly string s_pipePrefix = Path.Combine(Path.GetTempPath(), "CoreFxPipe_"); public override bool CanRead => true; public override bool CanSeek => false; public override bool CanWrite => true; public override long Length => 0L; public override long Position { get { return 0L; } set { } } public bool IsConnected => Native.IsConnected(ptr); public string PipeName { get; } public NamedPipeClientStream(string server, string pipeName) { ptr = Native.CreateClient(); PipeName = FormatPipe(server, pipeName); Console.WriteLine("Created new NamedPipeClientStream '{0}' => '{1}'", pipeName, PipeName); } ~NamedPipeClientStream() { Dispose(disposing: false); } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (!_isDisposed) { Disconnect(); Native.DestroyClient(ptr); _isDisposed = true; } } private static string FormatPipe(string server, string pipeName) { PlatformID platform = Environment.OSVersion.Platform; if (platform == PlatformID.Win32NT || platform != PlatformID.Unix) { return $"\\\\{server}\\pipe\\{pipeName}"; } if (server != ".") { throw new PlatformNotSupportedException("Remote pipes are not supported on this platform."); } return s_pipePrefix + pipeName; } public void Connect() { int err = Native.Open(ptr, PipeName); if (!IsConnected) { throw new NamedPipeOpenException(err); } } public void Disconnect() { Native.Close(ptr); } public override int Read(byte[] buffer, int offset, int count) { if (!IsConnected) { throw new NamedPipeConnectionException("Cannot read stream as pipe is not connected"); } if (offset + count > buffer.Length) { throw new ArgumentOutOfRangeException("count", "Cannot read as the count exceeds the buffer size"); } int num = 0; int cb = Marshal.SizeOf(buffer[0]) * count; IntPtr intPtr = Marshal.AllocHGlobal(cb); try { num = Native.ReadFrame(ptr, intPtr, count); if (num <= 0) { if (num < 0) { throw new NamedPipeReadException(num); } return 0; } Marshal.Copy(intPtr, buffer, offset, num); return num; } finally { Marshal.FreeHGlobal(intPtr); } } public override void Write(byte[] buffer, int offset, int count) { if (!IsConnected) { throw new NamedPipeConnectionException("Cannot write stream as pipe is not connected"); } int cb = Marshal.SizeOf(buffer[0]) * count; IntPtr intPtr = Marshal.AllocHGlobal(cb); try { Marshal.Copy(buffer, offset, intPtr, count); int num = Native.WriteFrame(ptr, intPtr, count); if (num < 0) { throw new NamedPipeWriteException(num); } } finally { Marshal.FreeHGlobal(intPtr); } } public override void Flush() { throw new NotSupportedException(); } public override long Seek(long offset, SeekOrigin origin) { throw new NotSupportedException(); } public override void SetLength(long value) { throw new NotSupportedException(); } } internal class Program { private const string LIBRARY_NAME = "NativeNamedPipe"; private const string PIPE_NAME = "testpipe"; private static CancellationTokenSource source; [DllImport("NativeNamedPipe", CallingConvention = CallingConvention.Cdecl)] private static extern bool test(int a, int b, IntPtr @out); private static void TestPipe() { using NamedPipeClientStream namedPipeClientStream = new NamedPipeClientStream(".", "testpipe"); try { Console.WriteLine("CLIENT: Connecting..."); namedPipeClientStream.Connect(); string text = "Hello World!"; Console.WriteLine("CLIENT: Sending '{0}'...", text); byte[] bytes = Encoding.ASCII.GetBytes(text); namedPipeClientStream.Write(bytes, 0, bytes.Length); Console.WriteLine("CLIENT: Sent. Reading message..."); text = ""; int num = 0; byte[] array = new byte[2048]; while ((num = namedPipeClientStream.Read(array, 0, array.Length)) == 0) { Console.Write("."); Thread.Sleep(1); } Console.WriteLine(); text = Encoding.ASCII.GetString(array, 0, num); Console.WriteLine("CLIENT: Server said '{0}'", text); } catch (Exception ex) { Console.WriteLine("Failed pipe test: {0}", ex.Message); } } private static void Main(string[] args) { if (ValidateDll()) { Console.WriteLine("Starting Server..."); source = new CancellationTokenSource(); Task.Factory.StartNew((Func<Task>)async delegate { await ServerIO(source.Token); }, source.Token); Console.WriteLine("How many times do you wish the test to be run?"); string text = Console.ReadLine(); if (string.IsNullOrWhiteSpace(text)) { text = "1"; } int num = int.Parse(text); for (int i = 0; i < num; i++) { Console.WriteLine("Testing Pipe #{0}....", i); TestPipe(); } Console.WriteLine("Canceling Token..."); source.Cancel(); source.Dispose(); Console.WriteLine("Press any key to exit."); Console.ReadKey(intercept: true); } } private static async Task ServerIO(CancellationToken token) { using NamedPipeServerStream server = new NamedPipeServerStream("testpipe", PipeDirection.InOut); while (!token.IsCancellationRequested) { Console.WriteLine("SERVER: Waiting for connection..."); string message3 = ""; await server.WaitForConnectionAsync(token); Console.WriteLine("SERVER: Connection established. Reading message..."); byte[] buffer = new byte[2048]; int bytesRead = await server.ReadAsync(buffer, 0, buffer.Length); Console.WriteLine("SERVER: Read {0} bytes", bytesRead); string msg = Encoding.ASCII.GetString(buffer, 0, bytesRead); message3 += msg; char[] chars = message3.ToCharArray(); Array.Reverse((Array)chars); message3 = new string(chars); Console.WriteLine("SERVER: Message read. Returning message '{0}'...", message3); byte[] msgbytes = Encoding.ASCII.GetBytes(message3); await server.WriteAsync(msgbytes, 0, msgbytes.Length); Console.WriteLine("SERVER: Disconnecting..."); server.Disconnect(); } } private static bool ValidateDll() { IntPtr intPtr = Marshal.AllocHGlobal(4); try { return test(-10, 10, intPtr) && Marshal.ReadInt32(intPtr) == 0; } catch (Exception ex) { Console.WriteLine("Failed DLL Test!"); Console.WriteLine(ex.Message); return false; } finally { Marshal.FreeHGlobal(intPtr); } } } } namespace Lachee.IO.Exceptions { public class NamedPipeConnectionException : Exception { internal NamedPipeConnectionException(string message) : base(message) { } } public class NamedPipeOpenException : Exception { public int ErrorCode { get; private set; } internal NamedPipeOpenException(int err) : base("An exception has occured while trying to open the pipe. Error Code: " + err) { ErrorCode = err; } } public class NamedPipeReadException : Exception { public int ErrorCode { get; private set; } internal NamedPipeReadException(int err) : base("An exception occured while reading from the pipe. Error Code: " + err) { ErrorCode = err; } } public class NamedPipeWriteException : Exception { public int ErrorCode { get; private set; } internal NamedPipeWriteException(int err) : base("An exception occured while reading from the pipe. Error Code: " + err) { ErrorCode = err; } } }