Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of RepoOmniShock v1.0.1
plugins/OmniShock/addzeey.OmniShock.dll
Decompiled 2 hours agousing System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Net.Http; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Threading; using System.Threading.Tasks; using BepInEx; using BepInEx.Configuration; using HarmonyLib; using MenuLib; using MenuLib.MonoBehaviors; using MenuLib.Structs; using Microsoft.CodeAnalysis; using OmniShock.Core; using OmniShock.Repo.Menu; using Photon.Pun; using TMPro; using UnityEngine; using UnityEngine.Events; using UnityEngine.InputSystem; using UnityEngine.InputSystem.Controls; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("addzeey.OmniShock")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.1.0")] [assembly: AssemblyInformationalVersion("1.0.1")] [assembly: AssemblyProduct("addzeey.OmniShock")] [assembly: AssemblyTitle("addzeey.OmniShock")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.1.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [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 OmniShock.Repo { internal readonly struct BreakObservation { internal readonly int Id; internal readonly float Lost; internal readonly float Original; internal readonly double Occurred; internal double Due => Occurred + 0.15; internal BreakObservation(int id, float lost, float original, double occurred) { Id = id; Lost = lost; Original = original; Occurred = occurred; } internal bool IsStale(double now) { return now - Due > 0.5; } } internal sealed class BreakObservationBuffer { internal const double CollisionWindowSeconds = 0.15; internal const double MaximumLatenessSeconds = 0.5; internal const double MaximumAgeSeconds = 0.65; internal const int Capacity = 128; private readonly Queue<BreakObservation> _observations = new Queue<BreakObservation>(); internal bool TryAdd(int id, float lost, float original, double occurred) { if (_observations.Count >= 128 || double.IsNaN(occurred) || double.IsInfinity(occurred) || lost <= 0f || float.IsNaN(lost) || float.IsInfinity(lost) || original <= 0f || float.IsNaN(original) || float.IsInfinity(original)) { return false; } _observations.Enqueue(new BreakObservation(id, lost, original, occurred)); return true; } internal bool TryTakeReady(double now, out BreakObservation observation) { observation = default(BreakObservation); if (double.IsNaN(now) || double.IsInfinity(now) || _observations.Count == 0 || _observations.Peek().Due > now) { return false; } observation = _observations.Dequeue(); return true; } internal void Clear() { _observations.Clear(); } } internal sealed class CredentialEntry { private string _value; private readonly Action _changed; internal ConfigDefinition Definition { get; } internal string Value { get { return _value; } set { if (!(_value == value)) { _value = value; _changed(); } } } internal CredentialEntry(string section, string key, string value, Action changed) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown Definition = new ConfigDefinition(section, key); _value = value; _changed = changed; } public override string ToString() { return "Credential (hidden)"; } } internal sealed class CredentialSettings { private readonly LocalCredentialStore _store; private CredentialSnapshot _saved; internal readonly CredentialEntry PiKey; internal readonly CredentialEntry PiId; internal readonly CredentialEntry OpenKey; internal readonly CredentialEntry OpenId; internal IReadOnlyList<CredentialEntry> Entries { get; } internal string Revision => _saved.Revision; internal bool IsCurrent => _store.Read().Revision == _saved.Revision; internal event EventHandler? Changed; internal CredentialSettings(ConfigFile config, ConfigEntry<bool> enabled, LocalCredentialStore store) { CredentialSettings credentialSettings = this; _store = store; _saved = store.Read(); DiscardConfigCredential("PiShock", "ApiKey"); DiscardConfigCredential("PiShock", "ShockerId"); DiscardConfigCredential("OpenShock", "ApiKey"); DiscardConfigCredential("OpenShock", "DeviceId"); config.Save(); PiKey = Entry("PiShock", "ApiKey"); PiId = Entry("PiShock", "ShockerId"); OpenKey = Entry("OpenShock", "ApiKey"); OpenId = Entry("OpenShock", "DeviceId"); Entries = new CredentialEntry[4] { PiKey, PiId, OpenKey, OpenId }; void DiscardConfigCredential(string section, string key) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected O, but got Unknown ConfigDefinition val = new ConfigDefinition(section, key); if (!string.IsNullOrWhiteSpace(config.Bind<string>(val, string.Empty, (ConfigDescription)null).Value)) { enabled.Value = false; } config.Remove(val); } CredentialEntry Entry(string section, string key) { string value; return new CredentialEntry(section, key, credentialSettings._saved.Values.TryGetValue(section + "/" + key, out value) ? (value ?? string.Empty) : string.Empty, delegate { credentialSettings.Changed?.Invoke(credentialSettings, EventArgs.Empty); }); } } internal Dictionary<string, string> SnapshotLive() { Dictionary<string, string> dictionary = _saved.Values.ToDictionary<KeyValuePair<string, string>, string, string>((KeyValuePair<string, string> pair) => pair.Key, (KeyValuePair<string, string> pair) => pair.Value, StringComparer.Ordinal); foreach (CredentialEntry entry in Entries) { dictionary[entry.Definition.Section + "/" + entry.Definition.Key] = entry.Value; } return dictionary; } internal void Refresh() { CredentialSnapshot val = _store.Read(); if (val.Revision == _saved.Revision) { return; } _saved = val; foreach (CredentialEntry entry in Entries) { entry.Value = (val.Values.TryGetValue(entry.Definition.Section + "/" + entry.Definition.Key, out var value) ? (value ?? string.Empty) : string.Empty); } } internal void Save(IReadOnlyDictionary<string, string> values) { CredentialSnapshot val = (_saved = _store.Write(values, _saved.Revision)); foreach (CredentialEntry entry in Entries) { entry.Value = val.Values[entry.Definition.Section + "/" + entry.Definition.Key]; } } } internal sealed class DiagnosticBuffer { internal const int Capacity = 256; internal const int PerFrameBudget = 32; private readonly ConcurrentQueue<string> _messages = new ConcurrentQueue<string>(); private int _count; private int _dropped; internal void Write(string message) { if (Interlocked.Increment(ref _count) > 256) { Interlocked.Decrement(ref _count); Interlocked.Increment(ref _dropped); } else { _messages.Enqueue(message); } } internal bool TryRead(out string message) { if (!_messages.TryDequeue(out message)) { return false; } Interlocked.Decrement(ref _count); return true; } internal int TakeDroppedCount() { return Interlocked.Exchange(ref _dropped, 0); } } [HarmonyPatch(typeof(PlayerHealth), "Hurt")] internal static class HealthLossHook { private static void Prefix(PlayerHealth __instance, out int __state) { __state = 0; try { __state = __instance.health; } catch (Exception exception) { Plugin.ReportHookFailure("Health snapshot", exception); } } private static void Postfix(PlayerHealth __instance, int __state) { try { Plugin instance = Plugin.Instance; if (!((Object)(object)instance == (Object)null) && instance.GameplayAllowed && instance.Settings.HurtEnabled.Value && Object.op_Implicit((Object)(object)__instance.playerAvatar)) { int intensity = ValuablePolicy.Intensity(TriggerPolicy.HealthLost(__state, __instance.health, __instance.playerAvatar.isLocal, instance.Alive), instance.Settings.DamageMultiplier.Value, instance.Settings.Maximum.Value); instance.Request("Local health lost", intensity, instance.Settings.HurtDurationMs.Value); } } catch (Exception exception) { Plugin.ReportHookFailure("Health loss", exception); } } } [HarmonyPatch(typeof(PlayerAvatar), "PlayerDeathRPC")] internal static class DeathHook { private struct Snapshot { internal bool WasDead; internal bool Local; internal bool Allowed; } private static void Prefix(PlayerAvatar __instance, out Snapshot __state) { __state = default(Snapshot); try { __state = new Snapshot { WasDead = __instance.deadSet, Local = __instance.isLocal, Allowed = (Plugin.Instance?.GameplayAllowed ?? false) }; } catch (Exception exception) { Plugin.ReportHookFailure("Death snapshot", exception); } } private static void Postfix(PlayerAvatar __instance, Snapshot __state) { try { Plugin instance = Plugin.Instance; if (!((Object)(object)instance == (Object)null) && TriggerPolicy.AcceptedDeath(__state.WasDead, __instance.deadSet, __state.Local, __state.Allowed)) { instance.ClearGameplayState(); if (instance.Settings.DeathEnabled.Value) { instance.Request("Local death", instance.Settings.DeathIntensity.Value, instance.Settings.DeathDurationMs.Value, acceptedDeath: true); } } } catch (Exception exception) { Plugin.ReportHookFailure("Local death", exception); } } } [HarmonyPatch(typeof(PlayerAvatar), "ReviveRPC")] internal static class ReviveHook { private static void Prefix(PlayerAvatar __instance, out bool __state) { __state = false; try { __state = __instance.deadSet; } catch (Exception exception) { Plugin.ReportHookFailure("Revive snapshot", exception); } } private static void Postfix(PlayerAvatar __instance, bool __state) { try { if (__instance.isLocal && __state && !__instance.deadSet) { Plugin.Instance?.ClearGameplayState(); } } catch (Exception exception) { Plugin.ReportHookFailure("Local revive", exception); } } } [HarmonyPatch(typeof(PhysGrabObject), "GrabStarted")] internal static class GrabHook { private static void Postfix(PhysGrabObject __instance, PhysGrabber player) { try { Plugin instance = Plugin.Instance; if (!((Object)(object)instance == (Object)null) && instance.GameplayAllowed && instance.Alive && __instance.isValuable && __instance.grabbedLocal && Object.op_Implicit((Object)(object)player) && player.isLocal) { instance.Valuables.Touch(((Object)__instance).GetInstanceID(), Time.realtimeSinceStartupAsDouble); } } catch (Exception exception) { Plugin.ReportHookFailure("Valuable grab", exception); } } } [HarmonyPatch(typeof(PhysGrabObject), "GrabEnded")] internal static class ReleaseHook { private static void Prefix(PhysGrabObject __instance, PhysGrabber player) { try { Plugin instance = Plugin.Instance; if (!((Object)(object)instance == (Object)null) && instance.GameplayAllowed && instance.Alive && __instance.isValuable && __instance.grabbedLocal && Object.op_Implicit((Object)(object)player) && player.isLocal) { instance.Valuables.Touch(((Object)__instance).GetInstanceID(), Time.realtimeSinceStartupAsDouble); } } catch (Exception exception) { Plugin.ReportHookFailure("Valuable release", exception); } } } [HarmonyPatch(typeof(PhysGrabObjectImpactDetector), "OnCollisionStay")] internal static class EnemyContactHook { private static void Prefix(PhysGrabObjectImpactDetector __instance, Collision collision) { try { Plugin instance = Plugin.Instance; if (!((Object)(object)instance == (Object)null) && instance.GameplayAllowed && instance.Alive && instance.Settings.IgnoreEnemies.Value && __instance.isValuable && Object.op_Implicit((Object)(object)__instance.physGrabObject) && collision != null) { Transform transform = collision.transform; if (Object.op_Implicit((Object)(object)transform) && (((Component)transform).CompareTag("Enemy") || Object.op_Implicit((Object)(object)((Component)transform).GetComponentInParent<EnemyRigidbody>()))) { PhysGrabObject physGrabObject = __instance.physGrabObject; instance.Valuables.EnemyContact(((Object)physGrabObject).GetInstanceID(), physGrabObject.heldByLocalPlayer || physGrabObject.grabbedLocal, Time.realtimeSinceStartupAsDouble, instance.Settings.ThrownGrace.Value, instance.Settings.HitGrace.Value); } } } catch (Exception exception) { Plugin.ReportHookFailure("Enemy contact", exception); } } } [HarmonyPatch(typeof(PhysGrabObjectImpactDetector), "BreakRPC")] internal static class ValuableLossHook { private struct Snapshot { internal int Id; internal float Loss; internal float Original; internal bool Held; internal bool Valid; } private static void Prefix(PhysGrabObjectImpactDetector __instance, float valueLost, bool _loseValue, PhotonMessageInfo _info, out Snapshot __state) { //IL_003c: Unknown result type (might be due to invalid IL or missing references) __state = default(Snapshot); try { Plugin instance = Plugin.Instance; if (!((Object)(object)instance == (Object)null) && instance.GameplayAllowed && instance.Alive && instance.Settings.BreakEnabled.Value && _loseValue && SemiFunc.MasterOnlyRPC(_info) && __instance.isValuable && Object.op_Implicit((Object)(object)__instance.valuableObject) && Object.op_Implicit((Object)(object)__instance.physGrabObject)) { ValuableObject valuableObject = __instance.valuableObject; float num = TriggerPolicy.BreakLoss(valuableObject.dollarValueCurrent, valuableObject.dollarValueOriginal, valueLost); if (!(num <= 0f)) { __state = new Snapshot { Id = ((Object)__instance.physGrabObject).GetInstanceID(), Loss = num, Original = valuableObject.dollarValueOriginal, Held = (__instance.physGrabObject.heldByLocalPlayer || __instance.physGrabObject.grabbedLocal), Valid = true }; } } } catch (Exception exception) { Plugin.ReportHookFailure("Valuable loss snapshot", exception); } } private static void Postfix(Snapshot __state) { try { if (__state.Valid) { Plugin.Instance?.QueueBreak(__state.Id, __state.Loss, __state.Original, __state.Held); } } catch (Exception exception) { Plugin.ReportHookFailure("Valuable loss", exception); } } } internal sealed class ModSettings { internal readonly ConfigEntry<bool> Enabled; internal readonly ConfigEntry<ShockProvider> Provider; internal readonly ConfigEntry<int> Maximum; internal readonly ConfigEntry<float> Cooldown; internal readonly ConfigEntry<string> PiUrl; internal readonly ConfigEntry<string> OpenUrl; internal readonly ConfigFile Config; internal readonly CredentialSettings Credentials; internal readonly ConfigEntry<bool> HurtEnabled; internal readonly ConfigEntry<bool> DeathEnabled; internal readonly ConfigEntry<bool> BreakEnabled; internal readonly ConfigEntry<bool> IgnoreEnemies; internal readonly ConfigEntry<bool> Proportional; internal readonly ConfigEntry<float> DamageMultiplier; internal readonly ConfigEntry<float> LossMultiplier; internal readonly ConfigEntry<float> ResponsibilityWindow; internal readonly ConfigEntry<float> ThrownGrace; internal readonly ConfigEntry<float> HitGrace; internal readonly ConfigEntry<int> HurtDurationMs; internal readonly ConfigEntry<int> DeathIntensity; internal readonly ConfigEntry<int> DeathDurationMs; internal readonly ConfigEntry<int> BreakDurationMs; internal CredentialEntry PiKey => Credentials.PiKey; internal CredentialEntry PiId => Credentials.PiId; internal CredentialEntry OpenKey => Credentials.OpenKey; internal CredentialEntry OpenId => Credentials.OpenId; internal ModSettings(ConfigFile config, LocalCredentialStore? credentialStore = null) { Config = config; bool saveOnConfigSet = config.SaveOnConfigSet; config.SaveOnConfigSet = false; try { Enabled = config.Bind<bool>("General", "Enabled", false, "Enable live device requests for local gameplay triggers."); ConfigEntry<bool> val = config.Bind<bool>("General", "DryRun", false, "Retired; migrated to Disabled."); if (val.Value) { Enabled.Value = false; } config.Remove(((ConfigEntryBase)val).Definition); Provider = config.Bind<ShockProvider>("General", "Provider", (ShockProvider)0, "PiShock V3 or OpenShock."); Maximum = Bind<int>("General", "MaxIntensity", 25, 1, 100, "Absolute cap on every outgoing shock."); Cooldown = Bind<float>("General", "CooldownSeconds", 2f, 0f, 60f, "Minimum interval between requests. Busy/cooldown events are dropped, not queued."); PiUrl = config.Bind<string>("PiShock", "ApiUrl", "https://api.pishock.com", "HTTPS API base URL; do not embed credentials."); OpenUrl = config.Bind<string>("OpenShock", "ApiUrl", "https://api.openshock.app", "HTTPS API base URL; self-hosted endpoints supported. Do not embed credentials."); HurtEnabled = config.Bind<bool>("Damage", "Enabled", true, "Trigger for actual local health lost, excluding lethal hits (handled by Death)."); DamageMultiplier = Bind<float>("Damage", "IntensityPerHealthLost", 1f, 0.01f, 100f, "Actual health lost multiplied by this value, rounded up and capped."); HurtDurationMs = Duration("Damage", 500); DeathEnabled = config.Bind<bool>("Death", "Enabled", true, "Trigger once per local death; remote deaths never trigger."); DeathIntensity = Bind<int>("Death", "Intensity", 25, 1, 100, "Death intensity, also limited by MaxIntensity."); DeathDurationMs = Duration("Death", 1000); BreakEnabled = config.Bind<bool>("Valuables", "Enabled", true, "Trigger for actual value lost on held or recently released valuables, including destruction."); Proportional = config.Bind<bool>("Valuables", "MapValueToIntensity", false, "Map value lost / original value to MaxIntensity instead of using ValueLossMultiplier."); LossMultiplier = Bind<float>("Valuables", "ValueLossMultiplier", 0.1f, 0.001f, 100f, "Value lost multiplied by this value, rounded up and capped."); ResponsibilityWindow = Bind<float>("Valuables", "ResponsibilityWindowSeconds", 15f, 1f, 120f, "How long each released valuable remains your responsibility."); BreakDurationMs = Duration("Valuables", 500); IgnoreEnemies = config.Bind<bool>("Valuables", "IgnoreHittingEnemies", true, "Suppress value-loss shocks for that item when used against enemies; does not suppress health damage."); ThrownGrace = Bind<float>("Valuables", "ThrownOffensiveGraceSeconds", 2f, 0f, 5f, "Released items must contact an enemy within this interval to qualify as thrown weapons."); HitGrace = Bind<float>("Valuables", "HitOffensiveGraceSeconds", 3f, 0f, 5f, "Suppress further damage on the SAME item after an eligible enemy contact."); Credentials = new CredentialSettings(config, Enabled, credentialStore ?? LocalCredentialStore.ForApplication("REPO")); } finally { config.SaveOnConfigSet = saveOnConfigSet; } ConfigEntry<T> Bind<T>(string section, string key, T value, T min, T max, string description) where T : notnull, IComparable { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown return config.Bind<T>(section, key, value, new ConfigDescription(description, (AcceptableValueBase)(object)new AcceptableValueRange<T>(min, max), Array.Empty<object>())); } ConfigEntry<int> Duration(string section, int value) { return Bind<int>(section, "DurationMilliseconds", value, 300, 15000, "Duration in milliseconds. 1000 = one second, for both providers."); } } internal ShockConnection Connection() { //IL_0006: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Expected O, but got Unknown if ((int)Provider.Value == 0) { return new ShockConnection(Provider.Value, PiUrl.Value, PiKey.Value, PiId.Value); } return new ShockConnection(Provider.Value, OpenUrl.Value, OpenKey.Value, OpenId.Value); } } [BepInPlugin("com.github.addzeey.OmniShock", "OmniShock", "1.0.1")] [BepInDependency("nickklmao.menulib", "2.6.2")] [BepInIncompatibility("mxpuffin.REPOShock")] [BepInIncompatibility("gay.lilyy.ReOpenShock")] public sealed class Plugin : BaseUnityPlugin { internal const string Guid = "com.github.addzeey.OmniShock"; private readonly ShockController _controller = new ShockController((HttpMessageHandler)null, (Func<double>)null); private readonly DiagnosticBuffer _messages = new DiagnosticBuffer(); private readonly BreakObservationBuffer _pendingBreaks = new BreakObservationBuffer(); private readonly HashSet<string> _reportedHookFailures = new HashSet<string>(); private CancellationTokenSource _scope = new CancellationTokenSource(); private Harmony? _harmony; private double _nextPrune; private double _nextDropReport; private long _configurationRevision; private long _appliedConfigurationRevision; private long _gameplayRevision; private bool _ready; private bool _settingsSavePaused; private bool _destroyed; internal static Plugin? Instance { get; private set; } internal ModSettings Settings { get; private set; } internal ValuablePolicy Valuables { get; } = new ValuablePolicy(); private bool LevelAllowed { get { if (_ready && !_destroyed && !_settingsSavePaused && ((Behaviour)this).isActiveAndEnabled && Settings.Enabled.Value && Object.op_Implicit((Object)(object)RunManager.instance) && Object.op_Implicit((Object)(object)RunManager.instance.levelCurrent) && !SemiFunc.RunIsArena() && !SemiFunc.RunIsRecording()) { if (!SemiFunc.RunIsLevel()) { return SemiFunc.RunIsTutorial(); } return true; } return false; } } internal bool GameplayAllowed { get { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Invalid comparison between Unknown and I4 if (LevelAllowed && Object.op_Implicit((Object)(object)GameDirector.instance)) { return (int)GameDirector.instance.currentState == 2; } return false; } } internal bool Alive { get { if (Object.op_Implicit((Object)(object)PlayerAvatar.instance) && !PlayerAvatar.instance.deadSet) { return !PlayerAvatar.instance.isDisabled; } return false; } } private void Awake() { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0028: Expected O, but got Unknown try { Settings = new ModSettings(((BaseUnityPlugin)this).Config); Instance = this; _harmony = new Harmony("com.github.addzeey.OmniShock"); _harmony.PatchAll(typeof(Plugin).Assembly); SceneManager.activeSceneChanged += OnSceneChanged; ((BaseUnityPlugin)this).Config.SettingChanged += OnSettingChanged; Settings.Credentials.Changed += OnCredentialsChanged; _ready = true; OmniShockMenu.Register(); } catch (Exception ex) { _ready = false; Instance = null; SceneManager.activeSceneChanged -= OnSceneChanged; ((BaseUnityPlugin)this).Config.SettingChanged -= OnSettingChanged; if (Settings != null) { Settings.Credentials.Changed -= OnCredentialsChanged; } try { Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } catch (Exception ex2) { ((BaseUnityPlugin)this).Logger.LogError((object)("Hook cleanup failed (" + ex2.GetType().Name + "). Restart before using OmniShock.")); } finally { _controller.Dispose(); } ((BaseUnityPlugin)this).Logger.LogError((object)("OmniShock hooks failed; no device requests will be sent. " + ex.GetType().Name + ": " + ex.Message)); return; } ((BaseUnityPlugin)this).Logger.LogInfo((object)("OmniShock loaded. Enabled=" + Settings.Enabled.Value + ". Enabled triggers send live device requests; no remote player controls your device.")); } internal void Request(string reason, int intensity, int durationMs, bool acceptedDeath = false, long? observedRevision = null) { //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Invalid comparison between Unknown and I4 ApplyConfigurationChanges(); if (observedRevision.HasValue && observedRevision.Value != _gameplayRevision) { _messages.Write("Valuable skipped: configuration or gameplay scope changed before dispatch."); return; } bool flag = acceptedDeath && LevelAllowed && Object.op_Implicit((Object)(object)GameDirector.instance) && (int)GameDirector.instance.currentState == 7; if ((GameplayAllowed || flag) && intensity > 0) { int num = Math.Clamp(Settings.Maximum.Value, 1, 100); intensity = Math.Clamp(intensity, 1, num); durationMs = Math.Clamp(durationMs, 300, 15000); long num2 = Interlocked.Read(in _configurationRevision); ShockConnection connection = Settings.Connection(); double cooldown = Settings.Cooldown.Value; if (num2 != _appliedConfigurationRevision || num2 != Interlocked.Read(in _configurationRevision)) { ApplyConfigurationChanges(); _messages.Write("Request skipped: configuration changed while capturing provider settings."); } else { SendAndReportAsync(connection, intensity, durationMs, num, cooldown, reason, _scope.Token); } } } private async Task SendAndReportAsync(ShockConnection connection, int intensity, int durationMs, int maximum, double cooldown, string reason, CancellationToken token) { try { ShockOutcome val = await _controller.SendAsync(connection, intensity, durationMs, "OmniShock", maximum, cooldown, false, token).ConfigureAwait(continueOnCapturedContext: false); _messages.Write($"{reason}: {val}; {connection.Provider}, intensity={intensity}%, duration={durationMs}ms."); } catch (Exception ex) { _messages.Write("Device request failed (" + ex.GetType().Name + "). Check local provider configuration."); } } internal void QueueBreak(int id, float lost, float original, bool held) { ApplyConfigurationChanges(); if (GameplayAllowed && Alive && Settings.BreakEnabled.Value && !(lost <= 0f) && Valuables.IsResponsible(id, held, Time.realtimeSinceStartupAsDouble, Settings.ResponsibilityWindow.Value) && !_pendingBreaks.TryAdd(id, lost, original, Time.realtimeSinceStartupAsDouble)) { _messages.Write("Valuable skipped: observation buffer full or invalid timestamp."); } } private void Update() { try { for (int i = 0; i < 32; i++) { if (!_messages.TryRead(out string message)) { break; } ((BaseUnityPlugin)this).Logger.LogInfo((object)message); } if (!_ready || _destroyed || (Object)(object)Instance != (Object)(object)this) { return; } ApplyConfigurationChanges(); double realtimeSinceStartupAsDouble = Time.realtimeSinceStartupAsDouble; if (realtimeSinceStartupAsDouble >= _nextDropReport) { int num = _messages.TakeDroppedCount(); if (num > 0) { ((BaseUnityPlugin)this).Logger.LogWarning((object)$"OmniShock omitted {num} repeated diagnostics to keep logging bounded."); } _nextDropReport = realtimeSinceStartupAsDouble + 1.0; } for (int j = 0; j < 128; j++) { if (!_pendingBreaks.TryTakeReady(realtimeSinceStartupAsDouble, out var observation)) { break; } long gameplayRevision = _gameplayRevision; if (observation.IsStale(realtimeSinceStartupAsDouble)) { _messages.Write("Valuable skipped: collision observation became stale."); continue; } if (!GameplayAllowed || !Alive || !Settings.BreakEnabled.Value) { _messages.Write("Valuable skipped: gameplay/local player/event no longer eligible."); continue; } if (Settings.IgnoreEnemies.Value && Valuables.IsOffensive(observation.Id, observation.Occurred)) { _messages.Write("Valuable skipped: this item's enemy-contact grace covers the loss."); continue; } int intensity = ValuablePolicy.Intensity(observation.Lost, Settings.LossMultiplier.Value, Settings.Maximum.Value, Settings.Proportional.Value, observation.Original); Request("Valuable value lost", intensity, Settings.BreakDurationMs.Value, acceptedDeath: false, gameplayRevision); } if (realtimeSinceStartupAsDouble >= _nextPrune) { Valuables.Prune(realtimeSinceStartupAsDouble, Math.Max(Settings.ResponsibilityWindow.Value, Settings.ThrownGrace.Value) + 1f); _nextPrune = realtimeSinceStartupAsDouble + 5.0; } } catch (Exception exception) { ReportHookFailure("Update", exception); } } private void OnSceneChanged(Scene previous, Scene next) { if (!_ready || _destroyed) { return; } try { OmniShockMenu.Close(); ResetScope(); } catch (Exception exception) { ReportHookFailure("Scene cleanup", exception); } } private void OnSettingChanged(object sender, SettingChangedEventArgs args) { Interlocked.Increment(ref _configurationRevision); } private void OnCredentialsChanged(object? sender, EventArgs args) { Interlocked.Increment(ref _configurationRevision); } private void ApplyConfigurationChanges() { long num = Interlocked.Read(in _configurationRevision); if (num != _appliedConfigurationRevision) { _appliedConfigurationRevision = num; ResetScope(); _messages.Write("Configuration changed: cleared item observations and cancelled previous request scope."); } } internal void ClearGameplayState() { _gameplayRevision++; _pendingBreaks.Clear(); Valuables.Clear(); } internal void ResetScope() { ClearGameplayState(); CancelScope(); _scope = new CancellationTokenSource(); } internal void PauseForSettingsSave() { _settingsSavePaused = true; ResetScope(); } internal void ResumeAfterSettingsSave() { _settingsSavePaused = false; } private void CancelScope() { try { _scope.Cancel(); } catch (AggregateException) { _messages.Write("A request cancellation callback failed; request scope was still closed."); } catch (ObjectDisposedException) { _messages.Write("Request scope was already closed."); } finally { _scope.Dispose(); } } internal static void ReportHookFailure(string hook, Exception exception) { Plugin instance = Instance; if ((Object)(object)instance != (Object)null && instance._reportedHookFailures.Add(hook)) { instance._messages.Write(hook + " failed (" + exception.GetType().Name + "); event skipped, game method left untouched. Repeated errors for this hook are muted."); } } private void OnDisable() { if (_ready && !_destroyed) { try { OmniShockMenu.Close(); ResetScope(); } catch (Exception exception) { ReportHookFailure("Disable cleanup", exception); } } } private void OnDestroy() { if (_destroyed) { return; } _destroyed = true; _ready = false; OmniShockMenu.Close(); ((BaseUnityPlugin)this).Config.SettingChanged -= OnSettingChanged; if (Settings != null) { Settings.Credentials.Changed -= OnCredentialsChanged; } SceneManager.activeSceneChanged -= OnSceneChanged; Instance = null; try { Harmony? harmony = _harmony; if (harmony != null) { harmony.UnpatchSelf(); } } catch (Exception ex) { ((BaseUnityPlugin)this).Logger.LogError((object)("OmniShock hook unload failed (" + ex.GetType().Name + "). Restart before reloading this mod.")); } finally { CancelScope(); try { _controller.Dispose(); } finally { ClearGameplayState(); } } } } internal static class TriggerPolicy { internal static int HealthLost(int before, int after, bool local, bool alive) { if (!(local && alive) || before <= after || after <= 0) { return 0; } return before - after; } internal static bool AcceptedDeath(bool wasDead, bool isDead, bool local, bool allowedBefore) { return local && allowedBefore && !wasDead && isDead; } internal static float BreakLoss(float before, float original, float requested) { if (!IsPositiveFinite(before) || !IsPositiveFinite(original) || !IsPositiveFinite(requested)) { return 0f; } if (!((double)(before - requested) < (double)original * 0.15000000596046448)) { return Math.Min(before, requested); } return before; } private static bool IsPositiveFinite(float value) { if (value > 0f && !float.IsNaN(value)) { return !float.IsInfinity(value); } return false; } } internal sealed class ValuablePolicy { private sealed class ItemState { internal double LastHeld; internal readonly List<GraceWindow> OffensiveWindows = new List<GraceWindow>(); } private readonly struct GraceWindow { internal readonly double Start; internal readonly double End; internal GraceWindow(double start, double end) { Start = start; End = end; } } private const int MaximumGraceWindows = 8; private readonly Dictionary<int, ItemState> _items = new Dictionary<int, ItemState>(); internal void Touch(int id, double now) { if (!_items.TryGetValue(id, out ItemState value)) { value = (_items[id] = new ItemState()); } value.LastHeld = now; } internal bool IsResponsible(int id, bool heldLocally, double now, double window) { if (heldLocally) { Touch(id, now); } if (_items.TryGetValue(id, out ItemState value)) { return now - value.LastHeld <= window; } return false; } internal void EnemyContact(int id, bool heldLocally, double now, double thrownGrace, double hitGrace) { if (heldLocally) { Touch(id, now); } if (!_items.TryGetValue(id, out ItemState value) || (!heldLocally && now - value.LastHeld > thrownGrace)) { return; } List<GraceWindow> offensiveWindows = value.OffensiveWindows; double num = now - 0.15; double num2 = now + Math.Max(0.0, hitGrace); if (offensiveWindows.Count > 0 && num <= offensiveWindows[offensiveWindows.Count - 1].End) { GraceWindow graceWindow = offensiveWindows[offensiveWindows.Count - 1]; offensiveWindows[offensiveWindows.Count - 1] = new GraceWindow(graceWindow.Start, Math.Max(graceWindow.End, num2)); return; } if (offensiveWindows.Count == 8) { offensiveWindows.RemoveAt(0); } offensiveWindows.Add(new GraceWindow(num, num2)); } internal bool IsOffensive(int id, double occurred) { if (!_items.TryGetValue(id, out ItemState value)) { return false; } foreach (GraceWindow offensiveWindow in value.OffensiveWindows) { if (occurred >= offensiveWindow.Start && occurred <= offensiveWindow.End) { return true; } } return false; } internal void Prune(double now, double window) { List<int> list = new List<int>(); foreach (KeyValuePair<int, ItemState> item in _items) { item.Value.OffensiveWindows.RemoveAll((GraceWindow grace) => grace.End < now - 0.65); if (now - item.Value.LastHeld > window && item.Value.OffensiveWindows.Count == 0) { list.Add(item.Key); } } foreach (int item2 in list) { _items.Remove(item2); } } internal void Clear() { _items.Clear(); } internal static int Intensity(float amount, float multiplier, int maximum, bool proportional = false, float original = 0f) { if (float.IsNaN(amount) || float.IsInfinity(amount) || amount <= 0f || maximum <= 0 || float.IsNaN(multiplier) || float.IsInfinity(multiplier) || multiplier <= 0f) { return 0; } if (proportional && (float.IsNaN(original) || float.IsInfinity(original) || original <= 0f)) { return 0; } float num = (proportional ? (amount / original * (float)maximum) : (amount * multiplier)); return (int)Math.Min(Math.Clamp(maximum, 1, 100), Math.Ceiling(num)); } } } namespace OmniShock.Repo.Menu { internal sealed class MaskedKeyInput : MonoBehaviour { private REPOInputStringSystem? _input; private TMP_Text? _visible; private TMP_Text? _inactiveEditor; private SecretEdit? _edit; private Action<string>? _report; internal void Initialize(REPOInputField field, SecretEdit edit, Action<string> report) { _edit = edit; _report = report; _input = field.inputStringSystem; _visible = _input.inputTMP; _visible.richText = false; _inactiveEditor = Object.Instantiate<TMP_Text>(_visible, _visible.transform.parent); ((Object)((Component)_inactiveEditor).gameObject).name = "OmniShock credential editor - never rendered"; ((Component)_inactiveEditor).gameObject.SetActive(false); _inactiveEditor.richText = false; _inactiveEditor.text = string.Empty; _input.inputTMP = _inactiveEditor; _input.placeholder = string.Empty; _input.SetValue(string.Empty, false); _input.onValueChanged = OnEdited; RefreshVisible(); } private void OnEdited(string value) { if (_edit != null && Object.op_Implicit((Object)(object)_input)) { if (!_edit.StageReplacement(value)) { _input.SetValue(string.Empty, false); _report?.Invoke(_edit.Error); } RefreshVisible(); } } internal void CapturePending() { if (_edit != null && Object.op_Implicit((Object)(object)_input)) { string text = _input.currentValue ?? string.Empty; if (text.Length > 0 || _edit.HasReplacement) { OnEdited(text); } } } internal void PasteReplacement() { if (_edit != null && Object.op_Implicit((Object)(object)_input)) { string text = GUIUtility.systemCopyBuffer ?? string.Empty; if (_edit.StageReplacement(text)) { _input.SetValue(text.Trim(), false); } else { _input.SetValue(string.Empty, false); _report?.Invoke(_edit.Error); } RefreshVisible(); } } internal void ClearInput() { if (Object.op_Implicit((Object)(object)_input)) { _input.isFocused = false; _input.SetValue(string.Empty, false); } if (Object.op_Implicit((Object)(object)_inactiveEditor)) { _inactiveEditor.text = string.Empty; } RefreshVisible(); } private void LateUpdate() { RefreshVisible(); } private void RefreshVisible() { //IL_0059: Unknown result type (might be due to invalid IL or missing references) //IL_006f: Unknown result type (might be due to invalid IL or missing references) if (Object.op_Implicit((Object)(object)_visible) && _edit != null) { _visible.text = (_edit.HasReplacement ? "********" : "Type or paste replacement"); ((Graphic)_visible).color = (Color)((Object.op_Implicit((Object)(object)_input) && _input.isFocused) ? new Color(1f, 0.65f, 0.2f) : Color.white); } } private void OnDestroy() { ClearInput(); if (Object.op_Implicit((Object)(object)_input)) { _input.onValueChanged = null; } _edit?.Reset(); _report = null; } } [HarmonyPatch(typeof(REPOInputStringSystem), "Update")] internal static class MenuInputPrivacyPatch { private static bool Prefix(REPOInputStringSystem __instance) { try { if (!Object.op_Implicit((Object)(object)((Component)__instance).GetComponentInParent<OmniShockMenuPage>())) { return true; } Keyboard current = Keyboard.current; if (current == null || Mouse.current == null) { return false; } if (__instance.currentValue == null) { __instance.SetValue(string.Empty, false); } MaskedKeyInput component = ((Component)__instance).GetComponent<MaskedKeyInput>(); if (!Object.op_Implicit((Object)(object)component) || !__instance.isFocused || !current.ctrlKey.isPressed) { return true; } if (((ButtonControl)current.cKey).wasPressedThisFrame || ((ButtonControl)current.xKey).wasPressedThisFrame) { return false; } if (((ButtonControl)current.vKey).wasPressedThisFrame) { component.PasteReplacement(); return false; } return true; } catch (Exception exception) { Plugin.ReportHookFailure("Menu input privacy", exception); return false; } } } [HarmonyPatch(typeof(REPOInputStringSystem), "set_isFocused")] internal static class MenuInputFocusPatch { private static bool Prefix(REPOInputStringSystem __instance, bool value, ref bool ____isFocused) { try { if (value && !Object.op_Implicit((Object)(object)ChatUI.instance) && Object.op_Implicit((Object)(object)((Component)__instance).GetComponentInParent<OmniShockMenuPage>())) { ____isFocused = true; REPOInputStringSystem.hasAnyFocus = true; return false; } return true; } catch (Exception exception) { Plugin.ReportHookFailure("Menu input focus", exception); return false; } } } [HarmonyPatch(typeof(REPOInputField), "Update")] internal static class MenuInputDevicePatch { private static bool Prefix(REPOInputField __instance) { try { return !Object.op_Implicit((Object)(object)((Component)__instance).GetComponentInParent<OmniShockMenuPage>()) || Mouse.current != null; } catch (Exception exception) { Plugin.ReportHookFailure("Menu pointer input", exception); return false; } } } internal static class OmniShockMenu { [CompilerGenerated] private static class <>O { public static BuilderDelegate <0>__BuildMain; public static BuilderDelegate <1>__BuildLobby; public static BuilderDelegate <2>__BuildEscape; public static Action <3>__Open; } private static bool _registered; private static OmniShockMenuPage? _page; internal static void Register() { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_003d: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_0058: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Expected O, but got Unknown if (!_registered) { object obj = <>O.<0>__BuildMain; if (obj == null) { BuilderDelegate val = BuildMain; <>O.<0>__BuildMain = val; obj = (object)val; } MenuAPI.AddElementToMainMenu((BuilderDelegate)obj); object obj2 = <>O.<1>__BuildLobby; if (obj2 == null) { BuilderDelegate val2 = BuildLobby; <>O.<1>__BuildLobby = val2; obj2 = (object)val2; } MenuAPI.AddElementToLobbyMenu((BuilderDelegate)obj2); object obj3 = <>O.<2>__BuildEscape; if (obj3 == null) { BuilderDelegate val3 = BuildEscape; <>O.<2>__BuildEscape = val3; obj3 = (object)val3; } MenuAPI.AddElementToEscapeMenu((BuilderDelegate)obj3); _registered = true; } } private static void BuildMain(Transform parent) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) AddButton(parent, new Vector2(500f, 290f)); } private static void BuildLobby(Transform parent) { //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Unknown result type (might be due to invalid IL or missing references) MenuPageLobby componentInParent = ((Component)parent).GetComponentInParent<MenuPageLobby>(); if (Object.op_Implicit((Object)(object)componentInParent) && Object.op_Implicit((Object)(object)componentInParent.leaveButton)) { Vector3 val = parent.InverseTransformPoint(((Component)componentInParent.leaveButton).transform.position); AddButton(parent, new Vector2(val.x + 280f, val.y)); } } private static void BuildEscape(Transform parent) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) AddButton(parent, new Vector2(126f, 105f)); } private static void AddButton(Transform parent, Vector2 position) { //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Unknown result type (might be due to invalid IL or missing references) try { if (Object.op_Implicit((Object)(object)parent) && !Object.op_Implicit((Object)(object)((Component)parent).GetComponentInChildren<OmniShockMenuButton>(true))) { REPOButton obj = MenuAPI.CreateREPOButton("OmniShock", (Action)Open, parent, position); ((Component)obj).gameObject.AddComponent<OmniShockMenuButton>(); ((TMP_Text)obj.labelTMP).fontSize = 24f; obj.overrideButtonSize = new Vector2(100f, 26f); } } catch (Exception exception) { Plugin.ReportHookFailure("Menu entry", exception); } } private static void Open() { REPOPopupPage val = null; try { Plugin instance = Plugin.Instance; if (!((Object)(object)instance == (Object)null) && !Object.op_Implicit((Object)(object)_page)) { val = MenuAPI.CreateREPOPopupPage("OMNISHOCK", (PresetSide)0, false, true, 6f); _page = ((Component)val).gameObject.AddComponent<OmniShockMenuPage>(); _page.Initialize(instance, val); val.OpenPage(false); } } catch (Exception exception) { try { Close(); if (Object.op_Implicit((Object)(object)val)) { if (Object.op_Implicit((Object)(object)MenuManager.instance)) { MenuManager.instance.PageReactivatePageUnderThisPage(val.menuPage); MenuManager.instance.PageRemove(val.menuPage); } Object.Destroy((Object)(object)((Component)val).gameObject); } } catch (Exception exception2) { Plugin.ReportHookFailure("Settings cleanup", exception2); } finally { _page = null; Plugin.ReportHookFailure("Open settings", exception); } } } internal static void Close() { try { if (Object.op_Implicit((Object)(object)_page)) { _page.Close(); } } catch (Exception exception) { Plugin.ReportHookFailure("Close settings", exception); } } internal static void Released(OmniShockMenuPage page) { if (_page == page) { _page = null; } } } internal sealed class OmniShockMenuButton : MonoBehaviour { } internal sealed class OmniShockMenuPage : MonoBehaviour { private const float ContentWidth = 520f; private static readonly string[] Sections = new string[6] { "General", "Damage", "Death", "Valuables", "PiShock", "OpenShock" }; private readonly List<MaskedKeyInput> _secretInputs = new List<MaskedKeyInput>(); private readonly List<(SecretEdit Edit, REPOLabel Label)> _secretStatuses = new List<(SecretEdit, REPOLabel)>(); private readonly List<(SettingEdit Edit, REPOInputField Field)> _textInputs = new List<(SettingEdit, REPOInputField)>(); private readonly Dictionary<string, List<REPOScrollViewElement>> _providerRows = new Dictionary<string, List<REPOScrollViewElement>>(); private Plugin? _plugin; private REPOPopupPage? _popup; private SettingsDraft? _draft; private REPOLabel? _status; private bool _closing; private bool _prompt; private bool _applying; internal void Initialize(Plugin plugin, REPOPopupPage popup) { //IL_006b: 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_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Expected O, but got Unknown //IL_02da: Unknown result type (might be due to invalid IL or missing references) //IL_02e4: Expected O, but got Unknown _plugin = plugin; _popup = popup; _draft = new SettingsDraft(plugin.Settings, null, plugin.PauseForSettingsSave, plugin.ResumeAfterSettingsSave); popup.maskPadding = new Padding(0f, 0f, 0f, 100f); WidenPage(popup); popup.scrollView.scrollSpeed = 3f; popup.onEscapePressed = new ShouldCloseMenuDelegate(HandleEscape); popup.AddElement((BuilderDelegate)delegate { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_00a6: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) _status = MenuAPI.CreateREPOLabel("Draft changes. Apply updates this session.", (Transform)(object)popup.rectTransform, FooterPosition(46f)); ((TMP_Text)_status.labelTMP).fontSize = 13f; ((TMP_Text)_status.labelTMP).richText = false; ((TMP_Text)_status.labelTMP).textWrappingMode = (TextWrappingModes)1; ((TMP_Text)_status.labelTMP).overflowMode = (TextOverflowModes)0; ((REPOElement)_status).rectTransform.sizeDelta = new Vector2(520f, 48f); ((TMP_Text)_status.labelTMP).rectTransform.sizeDelta = ((REPOElement)_status).rectTransform.sizeDelta; }); string[] sections = Sections; foreach (string section in sections) { int childCount = ((Transform)popup.menuScrollBox.scroller).childCount; AddLabel(section.ToUpperInvariant(), 17); foreach (SettingEdit item in _draft.Entries.Where((SettingEdit edit) => edit.Section == section)) { AddSetting(item); } foreach (SecretEdit item2 in _draft.Secrets.Where((SecretEdit edit) => edit.Section == section)) { AddSecret(item2); } string text = section; if ((!(text == "PiShock") && !(text == "OpenShock")) || 1 == 0) { continue; } List<REPOScrollViewElement> list = new List<REPOScrollViewElement>(); for (int num2 = childCount; num2 < ((Transform)popup.menuScrollBox.scroller).childCount; num2++) { REPOScrollViewElement component = ((Component)((Transform)popup.menuScrollBox.scroller).GetChild(num2)).GetComponent<REPOScrollViewElement>(); if (Object.op_Implicit((Object)(object)component)) { list.Add(component); } } _providerRows.Add(section, list); } RefreshProviderVisibility(); REPOSlider[] componentsInChildren = ((Component)this).GetComponentsInChildren<REPOSlider>(true); for (int num = 0; num < componentsInChildren.Length; num++) { FitControlLabel((TMP_Text)(object)componentsInChildren[num].labelTMP); } REPOToggle[] componentsInChildren2 = ((Component)this).GetComponentsInChildren<REPOToggle>(true); for (int num = 0; num < componentsInChildren2.Length; num++) { FitControlLabel((TMP_Text)(object)componentsInChildren2[num].labelTMP); } popup.AddElement((BuilderDelegate)delegate { //IL_0032: 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_007d: Unknown result type (might be due to invalid IL or missing references) //IL_0082: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00d2: Unknown result type (might be due to invalid IL or missing references) AddFooterButton("Apply", Apply, (Transform)(object)popup.rectTransform, FooterPosition(18f)); AddFooterButton("Back", RequestClose, (Transform)(object)popup.rectTransform, FooterPosition(18f) + new Vector2(170f, 0f)); AddFooterButton("Disable", DisableShocks, (Transform)(object)popup.rectTransform, FooterPosition(18f) + new Vector2(340f, 0f)); }); } private static void WidenPage(REPOPopupPage popup) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0068: Unknown result type (might be due to invalid IL or missing references) //IL_008e: Unknown result type (might be due to invalid IL or missing references) //IL_0093: 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_00ab: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) Rect rect = popup.maskRectTransform.rect; float num = 520f - ((Rect)(ref rect)).width; popup.maskPadding = new Padding(0f, 0f, 0f - num, 100f); popup.menuScrollBox.scroller.SetSizeWithCurrentAnchors((Axis)0, 520f); RectTransform scrollBarRectTransform = popup.scrollBarRectTransform; ((Transform)scrollBarRectTransform).localPosition = ((Transform)scrollBarRectTransform).localPosition + new Vector3(num, 0f, 0f); Transform obj = ((Transform)popup.rectTransform).Find("Panel"); RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null); if (val != null) { rect = val.rect; val.SetSizeWithCurrentAnchors((Axis)0, ((Rect)(ref rect)).width + num); ((Transform)val).localPosition = ((Transform)val).localPosition + new Vector3(num * val.pivot.x, 0f, 0f); } } private static void FitControlLabel(TMP_Text label) { label.enableAutoSizing = true; label.fontSizeMin = 12f; label.fontSizeMax = 18f; label.textWrappingMode = (TextWrappingModes)1; } private Vector2 FooterPosition(float height) { //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001e: 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_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_0049: Unknown result type (might be due to invalid IL or missing references) //IL_004f: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Unknown result type (might be due to invalid IL or missing references) RectTransform maskRectTransform = _popup.maskRectTransform; RectTransform rectTransform = _popup.rectTransform; Rect rect = maskRectTransform.rect; float xMin = ((Rect)(ref rect)).xMin; rect = maskRectTransform.rect; Vector3 val = ((Transform)rectTransform).InverseTransformPoint(((Transform)maskRectTransform).TransformPoint(new Vector3(xMin, ((Rect)(ref rect)).yMin, 0f))); return new Vector2(val.x, val.y - 100f + height); } private void AddFooterButton(string text, Action action, Transform parent, Vector2 position) { //IL_0022: 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) REPOButton obj = MenuAPI.CreateREPOButton(text, (Action)delegate { Run(action); }, parent, position); ((TMP_Text)obj.labelTMP).fontSize = 20f; obj.overrideButtonSize = new Vector2(85f, 24f); } private void AddLabel(string text, int size) { //IL_0021: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown _popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform parent) { //IL_0009: Unknown result type (might be due to invalid IL or missing references) //IL_000f: 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_0067: 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_008d: Unknown result type (might be due to invalid IL or missing references) //IL_00a8: Unknown result type (might be due to invalid IL or missing references) REPOLabel val = MenuAPI.CreateREPOLabel(text, parent, default(Vector2)); ((TMP_Text)val.labelTMP).fontSize = size; ((TMP_Text)val.labelTMP).richText = false; ((TMP_Text)val.labelTMP).textWrappingMode = (TextWrappingModes)1; ((TMP_Text)val.labelTMP).overflowMode = (TextOverflowModes)0; Vector2 preferredValues = ((TMP_Text)val.labelTMP).GetPreferredValues(text, 520f, float.PositiveInfinity); ((REPOElement)val).rectTransform.sizeDelta = new Vector2(520f, Math.Max(size + 6, preferredValues.y + 4f)); ((TMP_Text)val.labelTMP).rectTransform.sizeDelta = ((REPOElement)val).rectTransform.sizeDelta; return ((REPOElement)val).rectTransform; }, 0f, 0f); } private void AddSetting(SettingEdit edit) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Expected O, but got Unknown string label = FriendlyName(edit.Key); string description = edit.Entry.Description.Description; _popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform parent) { //IL_004b: 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_02eb: Unknown result type (might be due to invalid IL or missing references) //IL_02f1: Unknown result type (might be due to invalid IL or missing references) //IL_034a: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_01b5: Unknown result type (might be due to invalid IL or missing references) //IL_01bb: Unknown result type (might be due to invalid IL or missing references) if (edit.Value is bool flag) { string text = label; Action<bool> obj = delegate(bool value) { edit.Value = value; }; bool flag2 = flag; return PadControl(((REPOElement)MenuAPI.CreateREPOToggle(text, obj, parent, default(Vector2), "ON", "OFF", flag2)).rectTransform); } string key; if (edit.Value is int num) { AcceptableValueRange<int> val = (AcceptableValueRange<int>)(object)edit.Entry.Description.AcceptableValues; if (edit.Key == "DurationMilliseconds") { SliderSteps steps = new SliderSteps(val.MinValue, val.MaxValue, 500f, num, " ms"); return PadControl(((REPOElement)CreateSteppedSlider(label, steps, num, delegate(float value) { edit.Value = (int)value; }, parent)).rectTransform); } string text2 = label; Action<int> action = delegate(int value) { edit.Value = value; }; int minValue = val.MinValue; int maxValue = val.MaxValue; int num2 = num; key = edit.Key; bool flag2 = ((key == "MaxIntensity" || key == "Intensity") ? true : false); string text3 = (flag2 ? "%" : ""); return PadControl(((REPOElement)MenuAPI.CreateREPOSlider(text2, string.Empty, action, parent, default(Vector2), minValue, maxValue, num2, "", text3, (BarBehavior)0)).rectTransform); } if (edit.Value is float current) { AcceptableValueRange<float> val2 = (AcceptableValueRange<float>)(object)edit.Entry.Description.AcceptableValues; SliderSteps steps2 = new SliderSteps(val2.MinValue, val2.MaxValue, 0.5f, current); return PadControl(((REPOElement)CreateSteppedSlider(label, steps2, current, delegate(float value) { edit.Value = value; }, parent)).rectTransform); } if (edit.Entry.SettingType.IsEnum) { Type type = edit.Entry.SettingType; string[] names = Enum.GetNames(type); return PadControl(((REPOElement)MenuAPI.CreateREPOSlider(label, string.Empty, (Action<string>)delegate(string option) { edit.Value = Enum.Parse(type, option); if (edit.Section == "General" && edit.Key == "Provider") { RefreshProviderVisibility(); } }, parent, names, edit.Value.ToString(), default(Vector2), "", "", (BarBehavior)0)).rectTransform); } string text4 = label; Action<string> obj2 = delegate(string value) { edit.Value = value ?? string.Empty; }; key = (string)edit.Value; REPOInputField val3 = MenuAPI.CreateREPOInputField(text4, obj2, parent, default(Vector2), false, "", key); val3.inputStringSystem.inputTMP.richText = false; _textInputs.Add((edit, val3)); FitControlLabel((TMP_Text)(object)val3.labelTMP); return PadControl(((REPOElement)val3).rectTransform); }, 0f, 0f); if (edit.Key != "Provider" && !string.IsNullOrWhiteSpace(description)) { AddLabel(description, 12); } } private static REPOSlider CreateSteppedSlider(string label, SliderSteps steps, float current, Action<float> changed, Transform parent) { //IL_0055: Unknown result type (might be due to invalid IL or missing references) //IL_005b: Unknown result type (might be due to invalid IL or missing references) //IL_0099: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown //IL_00be: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Expected O, but got Unknown string text = steps.Labels[Array.IndexOf(steps.Values, current)]; REPOSlider slider = MenuAPI.CreateREPOSlider(label, string.Empty, (Action<string>)delegate(string option) { changed(steps.ValueFor(option)); }, parent, steps.Labels, text, default(Vector2), "", "", (BarBehavior)0); Button[] componentsInChildren = ((Component)slider).GetComponentsInChildren<Button>(true); ((UnityEventBase)componentsInChildren[0].onClick).RemoveAllListeners(); ((UnityEvent)componentsInChildren[0].onClick).AddListener((UnityAction)delegate { slider.SetValue(Math.Max(0f, slider.value - 1f), true); }); ((UnityEventBase)componentsInChildren[1].onClick).RemoveAllListeners(); ((UnityEvent)componentsInChildren[1].onClick).AddListener((UnityAction)delegate { slider.SetValue(Math.Min(steps.Values.Length - 1, slider.value + 1f), true); }); return slider; } private static RectTransform PadControl(RectTransform control) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0029: Unknown result type (might be due to invalid IL or missing references) //IL_002f: Expected O, but got Unknown //IL_003a: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0046: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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_004e: Unknown result type (might be due to invalid IL or missing references) //IL_0060: Unknown result type (might be due to invalid IL or missing references) //IL_0065: 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_009b: Unknown result type (might be due to invalid IL or missing references) Transform parent = ((Transform)control).parent; RectTransform val = (RectTransform)new GameObject("Setting row", new Type[1] { typeof(RectTransform) }).transform; ((Transform)val).SetParent(parent, false); Vector2 val2 = (val.pivot = Vector2.zero); Vector2 anchorMin = (val.anchorMax = val2); val.anchorMin = anchorMin; Rect rect = control.rect; val.sizeDelta = new Vector2(520f, Math.Max(32f, ((Rect)(ref rect)).height) + 12f); ((Transform)control).SetParent((Transform)(object)val, false); ((Transform)control).localPosition = new Vector3(0f, 6f, 0f); return val; } private void AddSecret(SecretEdit edit) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0057: Expected O, but got Unknown //IL_006b: Unknown result type (might be due to invalid IL or missing references) //IL_007f: Expected O, but got Unknown //IL_008c: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: Expected O, but got Unknown AddLabel(FriendlyName(edit.Key) + " (private)", 15); _popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform parent) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0053: 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) REPOLabel val = MenuAPI.CreateREPOLabel(edit.Status, parent, default(Vector2)); ((TMP_Text)val.labelTMP).fontSize = 13f; ((TMP_Text)val.labelTMP).richText = false; ((TMP_Text)val.labelTMP).textWrappingMode = (TextWrappingModes)1; ((REPOElement)val).rectTransform.sizeDelta = new Vector2(520f, 48f); ((TMP_Text)val.labelTMP).rectTransform.sizeDelta = ((REPOElement)val).rectTransform.sizeDelta; _secretStatuses.Add((edit, val)); return ((REPOElement)val).rectTransform; }, 0f, 0f); MaskedKeyInput editor = null; _popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform parent) { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Unknown result type (might be due to invalid IL or missing references) Action<string> obj = delegate { }; string empty = string.Empty; REPOInputField val = MenuAPI.CreateREPOInputField("Replacement", obj, parent, default(Vector2), false, "", empty); editor = ((Component)val).gameObject.AddComponent<MaskedKeyInput>(); editor.Initialize(val, edit, SetStatus); _secretInputs.Add(editor); FitControlLabel((TMP_Text)(object)val.labelTMP); return PadControl(((REPOElement)val).rectTransform); }, 0f, 0f); _popup.AddElementToScrollView((ScrollViewBuilderDelegate)delegate(Transform parent) { //IL_0018: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0028: 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_0039: Unknown result type (might be due to invalid IL or missing references) //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0047: 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) RectTransform val = (RectTransform)new GameObject("Credential actions", new Type[1] { typeof(RectTransform) }).transform; ((Transform)val).SetParent(parent, false); Vector2 val2 = (val.pivot = Vector2.zero); Vector2 anchorMin = (val.anchorMax = val2); val.anchorMin = anchorMin; val.sizeDelta = new Vector2(520f, 34f); AddSecretButton("Paste", delegate { editor.PasteReplacement(); }, (Transform)(object)val, 0f); AddSecretButton("Keep saved", delegate { edit.Reset(); editor.ClearInput(); SetStatus("Pending replacement/clear discarded. Saved value unchanged."); }, (Transform)(object)val, 120f); AddSecretButton("Clear saved", delegate { Confirm("Clear credential?", "The saved value is removed only when you Apply. No device requests are sent.", delegate { edit.StageClear(); editor.ClearInput(); SetStatus("Credential clearing staged. Apply to save it."); }); }, (Transform)(object)val, 240f); return val; }, 0f, 0f); } private void AddSecretButton(string text, Action action, Transform parent, float x) { //IL_0029: 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_0071: Unknown result type (might be due to invalid IL or missing references) REPOButton obj = MenuAPI.CreateREPOButton(text, (Action)delegate { Run(action); }, parent, new Vector2(x, 5f)); ((TMP_Text)obj.labelTMP).enableAutoSizing = false; ((TMP_Text)obj.labelTMP).fontSize = 14f; Vector2 val = default(Vector2); ((Vector2)(ref val))..ctor(106f, 24f); obj.overrideButtonSize = val; ((REPOElement)obj).rectTransform.sizeDelta = val; } private void RefreshProviderVisibility() { if (_draft == null || !Object.op_Implicit((Object)(object)_popup)) { return; } string text = _draft.Get<object>("General", "Provider").ToString(); foreach (string key in _providerRows.Keys) { bool flag = key == text; foreach (REPOScrollViewElement item in _providerRows[key]) { if (!flag) { REPOInputField[] componentsInChildren = ((Component)item).GetComponentsInChildren<REPOInputField>(true); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].inputStringSystem.isFocused = false; } } item.visibility = flag; } } _popup.scrollView.UpdateElements(); } private void Apply() { if (_draft == null || _applying || _prompt) { return; } foreach (var textInput in _textInputs) { textInput.Edit.Value = (textInput.Field.inputStringSystem.currentValue ?? string.Empty).Trim(); } foreach (MaskedKeyInput secretInput in _secretInputs) { secretInput.CapturePending(); } string text = _draft.Validate(); if (text != null) { SetStatus(text); } else if (_draft.RequiresHardwareConfirmation) { Confirm("Apply live shock settings?", "Future gameplay can operate your device. No test shock is sent. Hardware stop controls remain your responsibility.", delegate { Commit(hardwareConfirmed: true); }); } else { Commit(hardwareConfirmed: false); } } private void Commit(bool hardwareConfirmed) { if (_draft == null || _closing) { return; } _applying = true; try { if (_draft.TryApply(hardwareConfirmed, out string message) || _draft.CredentialsSavedOnLastApply) { foreach (MaskedKeyInput secretInput in _secretInputs) { secretInput.ClearInput(); } } SetStatus(message); } finally { _applying = false; } } private void DisableShocks() { if ((Object)(object)_plugin == (Object)null) { return; } bool saveOnConfigSet = ((BaseUnityPlugin)_plugin).Config.SaveOnConfigSet; ((BaseUnityPlugin)_plugin).Config.SaveOnConfigSet = false; try { _plugin.Settings.Enabled.Value = false; _plugin.ResetScope(); try { ((BaseUnityPlugin)_plugin).Config.Save(); SetStatus("New shocks disabled. An accepted command cannot be recalled. Reopen to refresh settings."); } catch (Exception) { SetStatus("Shocks disabled for this session, but saving failed. Repair config permissions before restarting."); } } finally { ((BaseUnityPlugin)_plugin).Config.SaveOnConfigSet = saveOnConfigSet; } } private void Confirm(string title, string message, Action accepted) { //IL_005f: Unknown result type (might be due to invalid IL or missing references) if (_prompt || _closing) { return; } _prompt = true; REPOInputField[] componentsInChildren = ((Component)this).GetComponentsInChildren<REPOInputField>(); for (int i = 0; i < componentsInChildren.Length; i++) { componentsInChildren[i].inputStringSystem.isFocused = false; } MenuAPI.OpenPopup(title, new Color(1f, 0.65f, 0.2f), message, (Action)delegate { Run(delegate { _prompt = false; accepted(); }); }, (Action)delegate { _prompt = false; }); } private bool HandleEscape() { Run(RequestClose); return false; } private void RequestClose() { if (!_prompt) { SettingsDraft? draft = _draft; if (draft != null && draft.HasChanges) { Confirm("Discard unsaved changes?", "Unsaved settings and replacement credentials will be discarded.", Close); } else { Close(); } } } internal void Close() { if (_closing) { return; } _closing = true; try { ClearSecrets(); REPOInputField[] componentsInChildren = ((Component)this).GetComponentsInChildren<REPOInputField>(); foreach (REPOInputField obj in componentsInChildren) { ((Behaviour)obj).enabled = false; ((Behaviour)obj.inputStringSystem).enabled = false; } } finally { _draft?.Dispose(); if (Object.op_Implicit((Object)(object)_popup)) { _popup.ClosePage(false); } } } private void ClearSecrets() { foreach (MaskedKeyInput secretInput in _secretInputs) { if (Object.op_Implicit((Object)(object)secretInput)) { secretInput.ClearInput(); } } } private void SetStatus(string message) { if (Object.op_Implicit((Object)(object)_status)) { ((TMP_Text)_status.labelTMP).text = message; } } private void Update() { if (_closing) { return; } foreach (var secretStatus in _secretStatuses) { if (Object.op_Implicit((Object)(object)secretStatus.Label)) { ((TMP_Text)secretStatus.Label.labelTMP).text = secretStatus.Edit.Status; } } SettingsDraft? draft = _draft; if (draft != null && draft.HasConflict) { SetStatus("Config changed elsewhere. Reopen OmniShock before applying."); } } private void Run(Action action) { if (_closing) { return; } try { action(); } catch (Exception exception) { _prompt = false; SetStatus("Menu action failed. No credential contents are logged."); Plugin.ReportHookFailure("Configuration menu", exception); } } private void OnDestroy() { try { ClearSecrets(); } finally { _draft?.Dispose(); _plugin = null; OmniShockMenu.Released(this); } } private static string FriendlyName(string key) { return key switch { "ApiKey" => "API key", "ApiUrl" => "API URL", "ShockerId" => "Shocker ID", "DeviceId" => "Device / share ID", "MaxIntensity" => "Maximum intensity", "DurationMilliseconds" => "Duration", "CooldownSeconds" => "Cooldown (seconds)", "IntensityPerHealthLost" => "Intensity per health lost", "MapValueToIntensity" => "Scale by fraction of value lost", "ValueLossMultiplier" => "Value loss multiplier", "ResponsibilityWindowSeconds" => "Release window (s)", "IgnoreHittingEnemies" => "Ignore enemy hits", "ThrownOffensiveGraceSeconds" => "Thrown grace (s)", "HitOffensiveGraceSeconds" => "After-hit grace (s)", _ => key, }; } } internal sealed class SecretEdit { internal const int MaximumLength = 4096; internal const string Mask = "********"; private readonly CredentialEntry _entry; private string _replacement = string.Empty; private bool _clear; internal string Section => _entry.Definition.Section; internal string Key => _entry.Definition.Key; internal bool IsConfigured => !string.IsNullOrWhiteSpace(_entry.Value); internal bool HasReplacement => _replacement.Length > 0; internal bool HasChanges { get { if (!HasReplacement) { return _clear; } return true; } } internal bool WillBeConfigured { get { if (!_clear) { if (!HasReplacement) { return IsConfigured; } return true; } return false; } } internal string? Error { get; private set; } internal string Status { get { if (Error == null) { if (!_clear) { if (!HasReplacement) { if (!IsConfigured) { return "No value set"; } return "Value is set — hidden"; } return "Replacement staged — hidden"; } return "Will clear on Apply"; } return "Replacement rejected — not saved"; } } internal SecretEdit(CredentialEntry entry) { _entry = entry; } internal bool StageReplacement(string? value) { string text = (value ?? string.Empty).Trim(); Reset(); if (text.Length > 4096) { Error = "Credential exceeds the supported input length."; } else { switch (text) { case "********": case "Value is set — hidden": case "Key is set — hidden": Error = "A hidden-value placeholder is not a credential."; break; default: { string text2 = text; foreach (char c in text2) { if (char.IsControl(c) || char.IsWhiteSpace(c)) { Error = "Credential must be one value without internal whitespace or control characters."; break; } } break; } } } if (Error != null) { return false; } _replacement = text; return true; } internal void StageClear() { Reset(); _clear = true; } internal void AddWrite(Action<CredentialEntry, string> addWrite) { if (HasChanges) { addWrite(_entry, _clear ? string.Empty : _replacement); } } internal void Reset() { _replacement = string.Empty; _clear = false; Error = null; } public override string ToString() { return Status; } } internal sealed class SettingEdit { internal ConfigEntryBase Entry { get; } internal object Original { get; private set; } internal object Value { get; set; } internal string Section => Entry.Definition.Section; internal string Key => Entry.Definition.Key; internal bool HasChanges => !object.Equals(Original, Value); internal SettingEdit(ConfigEntryBase entry) { Entry = entry; Original = (Value = entry.BoxedValue); } internal string? Validate() { if (Value == null || Value.GetType() != Entry.SettingType) { return Section + "/" + Key + ": invalid value type."; } if (Value is float f && (float.IsNaN(f) || float.IsInfinity(f))) { return Section + "/" + Key + ": enter a finite number."; } if (Entry.SettingType.IsEnum && !Enum.IsDefined(Entry.SettingType, Value)) { return Section + "/" + Key + ": choose a supported option."; } AcceptableValueBase acceptableValues = Entry.Description.AcceptableValues; if (acceptableValues != null && !object.Equals(acceptableValues.Clamp(Value), Value)) { return Section + "/" + Key + ": value is outside the permitted range."; } if (Key == "ApiUrl" && Value is string text && (!Uri.TryCreate(text.Trim(), UriKind.Absolute, out Uri result) || result.Scheme != Uri.UriSchemeHttps || result.UserInfo.Length > 0 || result.Query.Length > 0 || result.Fragment.Length > 0)) { return Section + ": API URL must use HTTPS without credentials, query, or fragment."; } return null; } internal void Accept() { object original = (Value = Entry.BoxedValue); Original = original; } public override string ToString() { return Section + "/" + Key; } } internal sealed class SettingsDraft : IDisposable { private readonly ConfigFile _config; private readonly Action _save; private readonly Action? _pauseRequests; private readonly Action? _resumeRequests; private readonly ConfigEntry<bool> _enabled; private readonly CredentialSettings _credentials; private string _credentialRevision; private readonly List<SettingEdit> _entries = new List<SettingEdit>(); private readonly List<SecretEdit> _secrets = new List<SecretEdit>(); private int _commitThread; private volatile bool _hasConflict; private bool _disposed; internal IReadOnlyList<SettingEdit> Entries => _entries; internal IReadOnlyList<SecretEdit> Secrets => _secrets; internal bool HasConflict { get { if (!_hasConflict) { return _credentialRevision != _credentials.Revision; } return true; } } internal bool HasChanges { get { if (!_entries.Any((SettingEdit entry) => entry.HasChanges)) { return _secrets.Any((SecretEdit secret) => secret.HasChanges || secret.Error != null); } return true; } } internal bool RequiresHardwareConfirmation { get { if (HasChanges) { return Get<bool>("General", "Enabled"); } return false; } } internal bool CredentialsSavedOnLastApply { get; private set; } internal SettingsDraft(ModSettings settings, Action? save = null, Action? pauseRequests = null, Action? resumeRequests = null) { _config = settings.Config; _save = save ?? new Action(_config.Save); _pauseRequests = pauseRequests; _resumeRequests = resumeRequests; _enabled = settings.Enabled; _credentials = settings.Credentials; _credentials.Refresh(); _credentialRevision = _credentials.Revision; foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item in from pair in (IEnumerable<KeyValuePair<ConfigDefinition, ConfigEntryBase>>)_config orderby pair.Key.Section, pair.Key.Key select pair) { _entries.Add(new SettingEdit(item.Value)); } foreach (CredentialEntry entry in _credentials.Entries) { _secrets.Add(new SecretEdit(entry)); } _config.SettingChanged += OnSettingChanged; _credentials.Changed += OnCredentialsChanged; } internal T Get<T>(string section, string key) { return (T)_entries.Single((SettingEdit entry) => entry.Section == section && entry.Key == key).Value; } internal static bool IsCredential(ConfigDefinition definition) { if (definition.Section == "PiShock" || definition.Section == "OpenShock") { if (!(definition.Key == "ApiKey") && !(definition.Key == "ShockerId")) { return definition.Key == "DeviceId"; } return true; } return false; } internal string? Validate() { if (_disposed) { return "This settings page is closed. Reopen OmniShock."; } if (HasConflict) { return "Config changed elsewhere. Close and reopen this page before applying."; } foreach (SettingEdit entry in _entries) { string text = entry.Validate(); if (text != null) { return text; } } foreach (SecretEdit secret in _secrets) { if (secret.Error != null) { return secret.Section + "/" + secret.Key + ": " + secret.Error; } } try { if (!_credentials.IsCurrent) { return "Credentials changed in another profile. Close and reopen OmniShock before applying."; } } catch (Exception) { return "Credential storage is unavailable. Nothing was applied; check local file permissions."; } if (Get<bool>("General", "Enabled")) { string provider = Get<object>("General", "Provider").ToString(); if (_secrets.Any((SecretEdit secret) => secret.Section == provider && !secret.WillBeConfigured)) { return "Selected provider needs a key and device ID before enabling live shocks."; } } return null; } internal bool TryApply(bool hardwareConfirmed, out string message) { CredentialsSavedOnLastApply = false; string text = Validate(); if (text != null) { message = text; return false; } if (RequiresHardwareConfirmation && !hardwareConfirmed) { message = "Confirm live hardware settings before applying."; return false; } if (!HasChanges) { message = "No changes to apply."; return true; } List<(ConfigEntryBase, object, object)> list = new List<(ConfigEntryBase, object, object)>(); bool flag = Get<bool>("General", "Enabled"); foreach (SettingEdit item in _entries.Where((SettingEdit entry) => entry.HasChanges)) { if ((object)item.Entry != _enabled) { list.Add((item.Entry, item.Entry.BoxedValue, item.Value)); } } Dictionary<string, string> credentialWrites = _credentials.SnapshotLive(); bool flag2 = _secrets.Any((SecretEdit secret) => secret.HasChanges); foreach (SecretEdit secret in _secrets) { secret.AddWrite(delegate(CredentialEntry entry, string value) { credentialWrites[entry.Definition.Section + "/" + entry.Definition.Key] = value; }); } bool saveOnConfigSet = _config.SaveOnConfigSet; Volatile.Write(ref _commitThread, Thread.CurrentThread.ManagedThreadId); _config.SaveOnConfigSet = false; try { _enabled.Value = false; _pauseRequests?.Invoke(); foreach (var item2 in list) { item2.Item1.BoxedValue = item2.Item3; } if (HasConflict) { throw new InvalidOperationException("Concurrent configuration change."); } _save(); if (HasConflict) { throw new InvalidOperationException("Concurrent configuration change."); } if (flag2) { _credentials.Save(credentialWrites); CredentialsSavedOnLastApply = true; } _credentialRevision = _credentials.Revision; if (HasConflict) { throw new InvalidOperationException("Concurrent configuration change."); } if (flag) { _enabled.Value = true; if (HasConflict) { throw new InvalidOperationException("Concurrent configuration change."); } _save(); if (HasConflict) { throw new InvalidOperationException("Concurrent configuration change."); } } foreach (SettingEdit entry in _entries) { entry.Accept(); } foreach (SecretEdit secret2 in _secrets) { secret2.Reset(); } _resumeRequests?.Invoke(); message = (flag ? "Saved. Shocks resumed with updated settings." : "Saved. Shocks remain disabled."); return true; } catch (Exception) { _enabled.Value = false; if (!CredentialsSavedOnLastApply) { foreach (var item3 in list) { if (object.Equals(item3.Item1.BoxedValue, item3.Item3)) { item3.Item1.BoxedValue = item3.Item2; } } } else { _credentialRevision = _credentials.Revision; foreach (SettingEdit entry2 in _entries) { entry2.Accept(); } foreach (SecretEdit secret3 in _secrets) { secret3.Reset(); } } SettingEdit settingEdit = _entries.Single((SettingEdit entry) => (object)entry.Entry == _enabled); settingEdit.Value = false; try { _save(); settingEdit.Accept(); message = (CredentialsSavedOnLastApply ? "Credentials saved, but resuming failed. Shocks remain disabled; check settings before enabling." : "Save failed. Previous settings restored; shocks remain disabled. Check file permissions."); } catch (Exception) { message = (CredentialsSavedOnLastApply ? "Credentials saved; shocks disabled for this session. Config repair failed. Repair config before restarting." : "Save failed; shocks disabled for this session. Config repair failed. Repair config before restarting."); } return false; } finally { list.Clear(); credentialWrites.Clear(); _config.SaveOnConfigSet = saveOnConfigSet; Volatile.Write(ref _commitThread, 0); } } private void OnSettingChanged(object? sender, SettingChangedEventArgs args) { if (Thread.CurrentThread.ManagedThreadId != Volatile.Read(in _commitThread)) { _hasConflict = true; } } private void OnCredentialsChanged(object? sender, EventArgs args) { if (Thread.CurrentThread.ManagedThreadId != Volatile.Read(in _commitThread)) { _hasConflict = true; } } public void Dispose() { if (_disposed) { return; } _disposed = true; _config.SettingChanged -= OnSettingChanged; _credentials.Changed -= OnCredentialsChanged; foreach (SecretEdit secret in _secrets) { secret.Reset(); } } } internal sealed class SliderSteps { internal float[] Values { get; } internal string[] Labels { get; } internal SliderSteps(float minimum, float maximum, float step, float current, string suffix = "") { if (step <= 0f || minimum > maximum || float.IsNaN(current) || float.IsInfinity(current) || current < minimum || current > maximum) { throw new ArgumentOutOfRangeException("current"); } SortedSet<float> sortedSet = new SortedSet<float>(); int num = (int)Math.Ceiling(minimum / step); int num2 = (int)Math.Floor(maximum / step); for (int i = num; i <= num2; i++) { sortedSet.Add((float)i * step); } sortedSet.Add(current); Values = sortedSet.ToArray(); Labels = Values.Select((float value) => value.ToString("0.###", CultureInfo.InvariantCulture) + suffix).ToArray(); } internal float ValueFor(string label) { return Values[Array.IndexOf(Labels, label)]; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { public IgnoresAccessChecksToAttribute(string assemblyName) { } } }
plugins/OmniShock/OmniShock.Core.dll
Decompiled 2 hours agousing System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Net.Http; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Newtonsoft.Json; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("addzeey")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyDescription("Game-independent PiShock V3/OpenShock transport, bounded controller, and separate local credential storage.")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("OmniShock.Core")] [assembly: AssemblyTitle("OmniShock.Core")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [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 OmniShock.Core { public sealed class CredentialSnapshot { public IReadOnlyDictionary<string, string> Values { get; } public string Revision { get; } internal CredentialSnapshot(Dictionary<string, string> values, string revision) { Values = new ReadOnlyDictionary<string, string>(values); Revision = revision; } public override string ToString() { return "Credential snapshot (hidden)"; } } public sealed class LocalCredentialStore { private const int MaximumFileBytes = 65536; private const int MaximumValueLength = 4096; private readonly string _path; private static readonly UTF8Encoding Utf8 = new UTF8Encoding(encoderShouldEmitUTF8Identifier: false, throwOnInvalidBytes: true); public LocalCredentialStore(string path) { if (string.IsNullOrWhiteSpace(path) || !Path.IsPathRooted(path)) { throw new ArgumentException("Credential store requires an absolute path.", "path"); } _path = Path.GetFullPath(path); } public static LocalCredentialStore ForApplication(string application) { if (string.IsNullOrEmpty(application) || application.Length > 64) { throw new ArgumentException("Invalid credential-store application name.", "application"); } for (int i = 0; i < application.Length; i++) { bool flag; switch (application[i]) { case '-': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G': case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U': case 'V': case 'W': case 'X': case 'Y': case 'Z': case '_': case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g': case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n': case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u': case 'v': case 'w': case 'x': case 'y': case 'z': flag = true; break; default: flag = false; break; } if (!flag) { throw new ArgumentException("Invalid credential-store application name.", "application"); } } string folderPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); if (string.IsNullOrWhiteSpace(folderPath) || !Path.IsPathRooted(folderPath)) { throw new IOException("Per-user application data is unavailable; credentials were not loaded."); } return new LocalCredentialStore(Path.Combine(folderPath, "OmniShock", application, "credentials.json")); } public CredentialSnapshot Read() { //IL_00bb: Unknown result type (might be due to invalid IL or missing references) //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00d8: Expected O, but got Unknown byte[] array; try { using FileStream fileStream = new FileStream(_path, FileMode.Open, FileAccess.Read, FileShare.Read | FileShare.Delete); if (fileStream.Length <= 0 || fileStream.Length > 65536) { throw new InvalidDataException("Credential store has an invalid size."); } array = new byte[(int)fileStream.Length]; int num; for (int i = 0; i < array.Length; i += num) { num = fileStream.Read(array, i, array.Length - i); if (num == 0) { throw new InvalidDataException("Credential store is incomplete."); } } } catch (FileNotFoundException) { return new CredentialSnapshot(new Dictionary<string, string>(StringComparer.Ordinal), string.Empty); } catch (DirectoryNotFoundException) { return new CredentialSnapshot(new Dictionary<string, string>(StringComparer.Ordinal), string.Empty); } try { Dictionary<string, string> values = JsonConvert.DeserializeObject<Dictionary<string, string>>(Utf8.GetString(array), new JsonSerializerSettings { MaxDepth = 4, TypeNameHandling = (TypeNameHandling)0 }) ?? throw new InvalidDataException("Credential store is invalid."); Validate(values); return new CredentialSnapshot(values, Fingerprint(array)); } catch (Exception ex3) when (((ex3 is JsonException || ex3 is DecoderFallbackException) ? 1 : 0) != 0) { throw new InvalidDataException("Credential store cannot be read. Existing file was preserved."); } finally { Array.Clear(array, 0, array.Length); } } public CredentialSnapshot Write(IReadOnlyDictionary<string, string> values, string expectedRevision) { Dictionary<string, string> dictionary = new Dictionary<string, string>(StringComparer.Ordinal); foreach (KeyValuePair<string, string> value in values) { dictionary.Add(value.Key, value.Value); } Validate(dictionary); byte[] bytes = Utf8.GetBytes(JsonConvert.SerializeObject((object)dictionary, (Formatting)1)); if (bytes.Length > 65536) { throw new InvalidDataException("Credential store exceeds its size limit."); } string directoryName = Path.GetDirectoryName(_path); Directory.CreateDirectory(directoryName); using (new FileStream(_path + ".lock", FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.None)) { if (Read().Revision != expectedRevision) { throw new InvalidOperationException("Credentials changed elsewhere. Reopen settings before saving."); } string text = Fingerprint(bytes); if (text == expectedRevision) { Array.Clear(bytes, 0, bytes.Length); return new CredentialSnapshot(dictionary, text); } string text2 = Path.Combine(directoryName, ".credentials-" + Guid.NewGuid().ToString("N") + ".tmp"); try { using (FileStream fileStream = new FileStream(text2, FileMode.CreateNew, FileAccess.Write, FileShare.None)) { fileStream.Write(bytes, 0, bytes.Length); fileStream.Flush(flushToDisk: true); } ReplaceByRename(text2, _path); return new CredentialSnapshot(dictionary, text); } finally { if (File.Exists(text2)) { File.Delete(text2); } Array.Clear(bytes, 0, bytes.Length); } } } private static string Fingerprint(byte[] bytes) { using SHA256 sHA = SHA256.Create(); return Convert.ToBase64String(sHA.ComputeHash(bytes)); } private static void ReplaceByRename(string source, string destination) { bool flag; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { flag = MoveFileEx(source, destination, 9u); } else { if (!RuntimeInformation.IsOSPlatform(OSPlatform.Linux) && !RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) { throw new PlatformNotSupportedException("Atomic credential storage is unavailable on this platform."); } flag = Rename(source, destination) == 0; } if (!flag) { throw new IOException("Credential store replacement failed (OS error " + Marshal.GetLastWin32Error() + ")."); } } [DllImport("kernel32.dll", CharSet = CharSet.Unicode, EntryPoint = "MoveFileExW", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool MoveFileEx(string source, string destination, uint flags); [DllImport("libc", CharSet = CharSet.Ansi, EntryPoint = "rename", SetLastError = true)] private static extern int Rename(string source, string destination); private static void Validate(Dictionary<string, string> values) { if (values.Count > 32) { throw new InvalidDataException("Too many credential entries."); } foreach (KeyValuePair<string, string> value2 in values) { if (string.IsNullOrWhiteSpace(value2.Key) || value2.Key.Length > 128 || value2.Value == null || value2.Value.Length > 4096) { throw new InvalidDataException("Credential store contains an invalid entry."); } string value = value2.Value; for (int i = 0; i < value.Length; i++) { if (char.IsControl(value[i])) { throw new InvalidDataException("Credential store contains an invalid value."); } } } } } public enum ShockOutcome { Sent, DryRun, MissingCredentials, Cooldown, Busy, Disabled, Cancelled, Failed } public sealed class ShockController : IDisposable { private readonly object _gate = new object(); private readonly HttpClient _client; private readonly CancellationTokenSource _shutdown = new CancellationTokenSource(); private readonly Func<double> _clock; private double _lastRequest = double.NegativeInfinity; private bool _busy; private bool _disposed; private bool _cancellationComplete; private bool _resourcesDisposed; public ShockController(HttpMessageHandler? handler = null, Func<double>? clock = null) { _client = new HttpClient(handler ?? new HttpClientHandler { AllowAutoRedirect = false }); _client.Timeout = TimeSpan.FromSeconds(10.0); _clock = clock ?? ((Func<double>)(() => (double)Stopwatch.GetTimestamp() / (double)Stopwatch.Frequency)); } public async Task<ShockOutcome> SendAsync(ShockConnection connection, int intensity, int durationMs, string agentName, int maxIntensity = 100, double cooldownSeconds = 2.0, bool dryRun = true, CancellationToken cancellationToken = default(CancellationToken)) { if (connection == null) { return ShockOutcome.Failed; } if (intensity <= 0 || maxIntensity <= 0) { return ShockOutcome.Disabled; } if (double.IsNaN(cooldownSeconds) || double.IsInfinity(cooldownSeconds)) { return ShockOutcome.Disabled; } intensity = Math.Clamp(intensity, 1, Math.Clamp(maxIntensity, 1, 100)); durationMs = Math.Clamp(durationMs, 300, 15000); lock (_gate) { if (_disposed || cancellationToken.IsCancellationRequested) { return ShockOutcome.Cancelled; } if (_busy) { return ShockOutcome.Busy; } double num = _clock(); if (double.IsNaN(num) || double.IsInfinity(num)) { return ShockOutcome.Failed; } if (num - _lastRequest < Math.Max(0.0, cooldownSeconds)) { return ShockOutcome.Cooldown; } if (!dryRun && !connection.IsConfigured) { return ShockOutcome.MissingCredentials; } _lastRequest = num; if (dryRun) { return ShockOutcome.DryRun; } _busy = true; } try { using CancellationTokenSource linked = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _shutdown.Token); using HttpResponseMessage httpResponseMessage = await ShockTransport.SendAsync(_client, connection, intensity, durationMs, agentName, linked.Token).ConfigureAwait(continueOnCapturedContext: false); return (!httpResponseMessage.IsSuccessStatusCode) ? ShockOutcome.Failed : ShockOutcome.Sent; } catch (OperationCanceledException) { return (cancellationToken.IsCancellationRequested || _shutdown.IsCancellationRequested) ? ShockOutcome.Cancelled : ShockOutcome.Failed; } catch (Exception ex2) when (ex2 is HttpRequestException || ex2 is ArgumentException || ex2 is InvalidOperationException || ex2 is FormatException) { return ShockOutcome.Failed; } finally { bool flag; lock (_gate) { _busy = false; flag = ReserveResourceDisposal(); } if (flag) { DisposeResources(); } } } public void Dispose() { lock (_gate) { if (_disposed) { return; } _disposed = true; } try { _shutdown.Cancel(); } catch (AggregateException) { } finally { bool flag; lock (_gate) { _cancellationComplete = true; flag = ReserveResourceDisposal(); } if (flag) { DisposeResources(); } } } private bool ReserveResourceDisposal() { if (!_disposed || !_cancellationComplete || _busy || _resourcesDisposed) { return false; } _resourcesDisposed = true; return true; } private void DisposeResources() { try { _client.Dispose(); } finally { _shutdown.Dispose(); } } } public enum ShockProvider { PiShock, OpenShock } public sealed class ShockConnection { public ShockProvider Provider { get; } public string ApiUrl { get; } public string ApiKey { get; } public string DeviceId { get; } public bool IsConfigured { get { if (!string.IsNullOrWhiteSpace(ApiKey)) { return !string.IsNullOrWhiteSpace(DeviceId); } return false; } } public ShockConnection(ShockProvider provider, string? apiUrl, string? apiKey, string? deviceId) { Provider = provider; ApiUrl = (apiUrl ?? string.Empty).Trim().TrimEnd('/'); ApiKey = (apiKey ?? string.Empty).Trim(); DeviceId = (deviceId ?? string.Empty).Trim(); } } public static class ShockTransport { public static HttpRequestMessage CreateRequest(ShockConnection connection, int intensity, int durationMs, string agentName) { if (connection == null) { throw new ArgumentNullException("connection"); } if (!Enum.IsDefined(typeof(ShockProvider), connection.Provider)) { throw new ArgumentOutOfRangeException("connection"); } if (!connection.IsConfigured) { throw new ArgumentException("Provider credentials are incomplete.", "connection"); } if (!Uri.TryCreate(connection.ApiUrl, UriKind.Absolute, out Uri result) || result.Scheme != Uri.UriSchemeHttps || !string.IsNullOrEmpty(result.UserInfo) || !string.IsNullOrEmpty(result.Query) || !string.IsNullOrEmpty(result.Fragment)) { throw new ArgumentException("Provider URL must use HTTPS without credentials, query, or fragment.", "connection"); } intensity = Math.Clamp(intensity, 1, 100); durationMs = Math.Clamp(durationMs, 300, 15000); bool flag = connection.Provider == ShockProvider.PiShock; string text = (flag ? ("/Shockers/OperateById/" + Uri.EscapeDataString(connection.DeviceId)) : "/2/shockers/control"); object obj = (flag ? ((object)new { AgentName = agentName, Intensity = intensity, Duration = durationMs, Operation = 0 }) : ((object)new { Shocks = new[] { new { Id = connection.DeviceId, Type = 1, Intensity = intensity, Duration = durationMs } }, CustomName = agentName })); HttpRequestMessage httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, connection.ApiUrl + text) { Content = new StringContent(JsonConvert.SerializeObject(obj), Encoding.UTF8, "application/json") }; try { httpRequestMessage.Headers.Add(flag ? "X-PiShock-Api-Key" : "OpenShockToken", connection.ApiKey); httpRequestMessage.Headers.Accept.ParseAdd("application/json"); httpRequestMessage.Headers.UserAgent.ParseAdd("OmniShock/1.0.0"); return httpRequestMessage; } catch { httpRequestMessage.Dispose(); throw; } } public static async Task<HttpResponseMessage> SendAsync(HttpClient client, ShockConnection connection, int intensity, int durationMs, string agentName, CancellationToken cancellationToken) { using HttpRequestMessage request = CreateRequest(connection, intensity, durationMs, agentName); return await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } } }
plugins/OmniShock/Newtonsoft.Json.dll
Decompiled 2 hours 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.Diagnostics.CodeAnalysis; 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("13.0.3.27908")] [assembly: AssemblyInformationalVersion("13.0.3+0a2e291c0d9c0c7675d445703e51750363a549ef")] [assembly: AssemblyProduct("Json.NET")] [assembly: AssemblyTitle("Json.NET .NET Standard 2.0")] [assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/JamesNK/Newtonsoft.Json")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: AssemblyVersion("13.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 { } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] internal sealed class NullableAttribute : Attribute { public readonly byte[] NullableFlags; public NullableAttribute(byte P_0) { NullableFlags = new byte[1] { P_0 }; } public NullableAttribute(byte[] P_0) { NullableFlags = P_0; } } [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } } namespace System.Diagnostics.CodeAnalysis { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, AllowMultiple = true)] internal sealed class NotNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false)] internal sealed class NotNullWhenAttribute : Attribute { public bool ReturnValue { get; } public NotNullWhenAttribute(bool returnValue) { ReturnValue = returnValue; } } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.ReturnValue, Inherited = false)] internal sealed class MaybeNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, Inherited = false)] internal sealed class AllowNullAttribute : Attribute { } [AttributeUsage(AttributeTargets.Parameter, Inherited = false)] internal class DoesNotReturnIfAttribute : Attribute { public bool ParameterValue { get; } public DoesNotReturnIfAttribute(bool parameterValue) { ParameterValue = parameterValue; } } } 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 = Volatile.Read(ref _mask); int num4 = num & num3; for (Entry entry = _entries[num4]; 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; Volatile.Write(ref _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.GetValueOrDefault(); } set { _isReference = value; } } public bool ItemIsReference { get { return _itemIsReference.GetValueOrDefault(); } set { _itemIsReference = value; } } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling.GetValueOrDefault(); } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling.GetValueOrDefault(); } 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) || StringUtils.IndexOf(text, '.') != -1 || StringUtils.IndexOf(text, 'E') != -1 || StringUtils.IndexOf(text, 'e') != -1) { return text; } return text + ".0"; } private static string EnsureDecimalPlace(string text) { if (StringUtils.IndexOf(text, '.') != -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.GetValueOrDefault(); } set { _missingMemberHandling = value; } } public NullValueHandling ItemNullValueHandling { get { return _itemNullValueHandling.GetValueOrDefault(); } set { _itemNullValueHandling = value; } } public Required ItemRequired { get { return _itemRequired.GetValueOrDefault(); } 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.GetValueOrDefault(); } set { _nullValueHandling = value; } } public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling.GetValueOrDefault(); } set { _defaultValueHandling = value; } } public ReferenceLoopHandling ReferenceLoopHandling { get { return _referenceLoopHandling.GetValueOrDefault(); } set { _referenceLoopHandling = value; } } public ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling.GetValueOrDefault(); } set { _objectCreationHandling = value; } } public TypeNameHandling TypeNameHandling { get { return _typeNameHandling.GetValueOrDefault(); } set { _typeNameHandling = value; } } public bool IsReference { get { return _isReference.GetValueOrDefault(); } set { _isReference = value; } } public int Order { get { return _order.GetValueOrDefault(); } set { _order = value; } } public Required Required { get { return _required.GetValueOrDefault(); } set { _required = value; } } public string? PropertyName { get; set; } public ReferenceLoopHandling ItemReferenceLoopHandling { get { return _itemReferenceLoopHandling.GetValueOrDefault(); } set { _itemReferenceLoopHandling = value; } } public TypeNameHandling ItemTypeNameHandling { get { return _itemTypeNameHandling.GetValueOrDefault(); } set { _itemTypeNameHandling = value; } } public bool ItemIsReference { get { return _itemIsReference.GetValueOrDefault(); } 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; _maxDepth = 64; 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; if (value is int) { return (int)value; } 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 (StringUtils.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; if (value is double) { return (double)value; } 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 (StringUtils.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 (StringUtils.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; if (value is decimal) { return (decimal)value; } 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 (StringUtils.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: return ReadDateTimeString((string)Value); default: throw JsonReaderException.Create(this, "Error reading date. Unexpected token: {0}.".FormatWith(CultureInfo.InvariantCulture, TokenType)); } } internal DateTime? ReadDateTimeString(string? s) { if (StringUtils.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 (StringUtils.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 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.GetValueOrDefault(); } set { _formatting = value; } } public virtual DateFormatHandling DateFormatHandling { get { return _dateFormatHandling.GetValueOrDefault(); } 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.GetValueOrDefault(); } set { _floatParseHandling = value; } } public virtual FloatFormatHandling FloatFormatHandling { get { return _floatFormatHandling.GetValueOrDefault(); } set { _floatFormatHandling = value; } } public virtual StringEscapeHandling StringEscapeHandling { get { return _stringEscapeHandling.GetValueOrDefault(); } 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.GetValueOrDefault(); } 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 CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string 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 CultureInfo previousCulture, out DateTimeZoneHandling? previousDateTimeZoneHandling, out DateParseHandling? previousDateParseHandling, out FloatParseHandling? previousFloatParseHandling, out int? previousMaxDepth, out string 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; } internal 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 const int DefaultMaxDepth = 64; 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.GetValueOrDefault(); } set { _referenceLoopHandling = value; } } public MissingMemberHandling MissingMemberHandling { get { return _missingMemberHandling.GetValueOrDefault(); } set { _missingMemberHandling = value; } } public ObjectCreationHandling ObjectCreationHandling { get { return _objectCreationHandling.GetValueOrDefault(); } set { _objectCreationHandling = value; } } public NullValueHandling NullValueHandling { get { return _nullValueHandling.GetValueOrDefault(); } set { _nullValueHandling = value; } } public DefaultValueHandling DefaultValueHandling { get { return _defaultValueHandling.GetValueOrDefault(); } set { _defaultValueHandling = value; } } public IList<JsonConverter> Converters { get; set; } public PreserveReferencesHandling PreserveReferencesHandling { get { return _preserveReferencesHandling.GetValueOrDefault(); } set { _preserveReferencesHandling = value; } } public TypeNameHandling TypeNameHandling { get { return _typeNameHandling.GetValueOrDefault(); } set {