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 RiskOfChaos v2.7.1
patchers/RiskOfChaos/RiskOfChaosPatcher.dll
Decompiled 6 months agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using BepInEx.Logging; using Microsoft.CodeAnalysis; using Mono.Cecil; [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("RiskOfChaosPatcher")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+185a0f39c4b3d300dea0a9a7bc277dc0938d8ec6")] [assembly: AssemblyProduct("RiskOfChaosPatcher")] [assembly: AssemblyTitle("RiskOfChaosPatcher")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace RiskOfChaosPatcher { internal static class AssemblyNames { public const string RoR2 = "RoR2.dll"; } internal sealed class LogWriter { private ManualLogSource _logSource; public LogWriter(ManualLogSource logSource) { _logSource = logSource; } public LogWriter() : this(null) { } public void SetLogSource(ManualLogSource logSource) { _logSource = logSource; } public void Fatal(object message) { ManualLogSource logSource = _logSource; if (logSource != null) { logSource.LogFatal(message); } } public void Error(object message) { ManualLogSource logSource = _logSource; if (logSource != null) { logSource.LogError(message); } } public void Warning(object message) { ManualLogSource logSource = _logSource; if (logSource != null) { logSource.LogWarning(message); } } public void Message(object message) { ManualLogSource logSource = _logSource; if (logSource != null) { logSource.LogMessage(message); } } public void Info(object message) { ManualLogSource logSource = _logSource; if (logSource != null) { logSource.LogInfo(message); } } [Conditional("DEBUG")] public void Debug(object message) { ManualLogSource logSource = _logSource; if (logSource != null) { logSource.LogDebug(message); } } } public static class ProjectilePatcher { private static readonly LogWriter _log = new LogWriter(); public static IEnumerable<string> TargetDLLs { get; } = new <>z__ReadOnlySingleElementList<string>("RoR2.dll"); public static void Initialize() { _log.SetLogSource(Logger.CreateLogSource("ProjectilePatcher")); } public static void Patch(AssemblyDefinition assembly) { //IL_0042: Unknown result type (might be due to invalid IL or missing references) //IL_004c: Expected O, but got Unknown TypeDefinition type = assembly.MainModule.GetType("RoR2.Projectile.FireProjectileInfo"); if (type == null) { _log.Error("Failed to find type: FireProjectileInfo"); return; } TypeReference val = assembly.MainModule.ImportReference(typeof(float)); addField(type, new FieldDefinition("roc_procCoefficientOverridePlusOne", (FieldAttributes)6, val)); } private static void addField(TypeDefinition declaringType, FieldDefinition field) { declaringType.Fields.Add(field); } } } [CompilerGenerated] internal sealed class <>z__ReadOnlySingleElementList<T> : IEnumerable, ICollection, IList, IEnumerable<T>, IReadOnlyCollection<T>, IReadOnlyList<T>, ICollection<T>, IList<T> { private sealed class Enumerator : IDisposable, IEnumerator, IEnumerator<T> { object IEnumerator.Current => _item; T IEnumerator<T>.Current => _item; public Enumerator(T item) { _item = item; } bool IEnumerator.MoveNext() { if (!_moveNextCalled) { return _moveNextCalled = true; } return false; } void IEnumerator.Reset() { _moveNextCalled = false; } void IDisposable.Dispose() { } } int ICollection.Count => 1; bool ICollection.IsSynchronized => false; object ICollection.SyncRoot => this; object IList.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } bool IList.IsFixedSize => true; bool IList.IsReadOnly => true; int IReadOnlyCollection<T>.Count => 1; T IReadOnlyList<T>.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } } int ICollection<T>.Count => 1; bool ICollection<T>.IsReadOnly => true; T IList<T>.this[int index] { get { if (index != 0) { throw new IndexOutOfRangeException(); } return _item; } set { throw new NotSupportedException(); } } public <>z__ReadOnlySingleElementList(T item) { _item = item; } IEnumerator IEnumerable.GetEnumerator() { return new Enumerator(_item); } void ICollection.CopyTo(Array array, int index) { array.SetValue(_item, index); } int IList.Add(object value) { throw new NotSupportedException(); } void IList.Clear() { throw new NotSupportedException(); } bool IList.Contains(object value) { return EqualityComparer<T>.Default.Equals(_item, (T)value); } int IList.IndexOf(object value) { if (!EqualityComparer<T>.Default.Equals(_item, (T)value)) { return -1; } return 0; } void IList.Insert(int index, object value) { throw new NotSupportedException(); } void IList.Remove(object value) { throw new NotSupportedException(); } void IList.RemoveAt(int index) { throw new NotSupportedException(); } IEnumerator<T> IEnumerable<T>.GetEnumerator() { return new Enumerator(_item); } void ICollection<T>.Add(T item) { throw new NotSupportedException(); } void ICollection<T>.Clear() { throw new NotSupportedException(); } bool ICollection<T>.Contains(T item) { return EqualityComparer<T>.Default.Equals(_item, item); } void ICollection<T>.CopyTo(T[] array, int arrayIndex) { array[arrayIndex] = _item; } bool ICollection<T>.Remove(T item) { throw new NotSupportedException(); } int IList<T>.IndexOf(T item) { if (!EqualityComparer<T>.Default.Equals(_item, item)) { return -1; } return 0; } void IList<T>.Insert(int index, T item) { throw new NotSupportedException(); } void IList<T>.RemoveAt(int index) { throw new NotSupportedException(); } }
plugins/RiskOfChaos/RiskOfChaos.dll
Decompiled 6 months ago
The result has been truncated due to the large size, download it to view full contents!
using System; using System.Collections; using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using AK.Wwise; using BepInEx; using BepInEx.Bootstrap; using BepInEx.Configuration; using BepInEx.Logging; using EntityStates; using EntityStates.Barrel; using EntityStates.Captain.Weapon; using EntityStates.Croco; using EntityStates.GoldGat; using EntityStates.GolemMonster; using EntityStates.Interactables.GoldBeacon; using EntityStates.Loader; using EntityStates.Merc; using EntityStates.Toolbot; using EntityStates.VoidInfestor; using HG; using HG.Coroutines; using HG.Reflection; using HarmonyLib; using IL.EntityStates; using IL.EntityStates.Bandit2.Weapon; using IL.EntityStates.Geode; using IL.EntityStates.GoldGat; using IL.EntityStates.GolemMonster; using IL.EntityStates.Merc; using IL.EntityStates.Railgunner.Scope; using IL.EntityStates.ShrineHalcyonite; using IL.EntityStates.Toolbot; using IL.EntityStates.VoidSurvivor.Weapon; using IL.RoR2; using IL.RoR2.CharacterAI; using IL.RoR2.Items; using IL.RoR2.Orbs; using IL.RoR2.Projectile; using IL.RoR2.Skills; using IL.RoR2.UI; using KinematicCharacterController; using Microsoft.CodeAnalysis; using Mono.Cecil; using Mono.Cecil.Cil; using Mono.Collections.Generic; using MonoMod.Cil; using MonoMod.RuntimeDetour; using MonoMod.Utils; using Newtonsoft.Json; using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using Newtonsoft.Json.Serialization; using On.RoR2; using On.RoR2.CameraModes; using On.RoR2.Orbs; using On.RoR2.Projectile; using On.RoR2.UI; using On.RoR2.UI.LogBook; using On.RoR2.UI.MainMenu; using ProperSave; using R2API; using R2API.Networking; using R2API.Networking.Interfaces; using R2API.Utils; using Rewired; using Rewired.ComponentControls.Effects; using RiskOfChaos.ChatMessages; using RiskOfChaos.Collections; using RiskOfChaos.Collections.CatalogIndex; using RiskOfChaos.Collections.ParsedValue; using RiskOfChaos.Components; using RiskOfChaos.Components.CostProviders; using RiskOfChaos.Components.MaterialInterpolation; using RiskOfChaos.ConfigHandling; using RiskOfChaos.ConfigHandling.AcceptableValues; using RiskOfChaos.Content; using RiskOfChaos.Content.Logbook; using RiskOfChaos.Content.Orbs; using RiskOfChaos.EffectDefinitions; using RiskOfChaos.EffectDefinitions.Character; using RiskOfChaos.EffectDefinitions.Character.Buff; using RiskOfChaos.EffectDefinitions.UI; using RiskOfChaos.EffectDefinitions.World; using RiskOfChaos.EffectDefinitions.World.Items; using RiskOfChaos.EffectDefinitions.World.Knockback; using RiskOfChaos.EffectDefinitions.World.RunTimer; using RiskOfChaos.EffectHandling; using RiskOfChaos.EffectHandling.Controllers; using RiskOfChaos.EffectHandling.Controllers.ChatVoting; using RiskOfChaos.EffectHandling.Controllers.ChatVoting.Twitch; using RiskOfChaos.EffectHandling.EffectClassAttributes; using RiskOfChaos.EffectHandling.EffectClassAttributes.Data; using RiskOfChaos.EffectHandling.EffectClassAttributes.Methods; using RiskOfChaos.EffectHandling.EffectComponents; using RiskOfChaos.EffectHandling.EffectComponents.SubtitleProviders; using RiskOfChaos.EffectHandling.Formatting; using RiskOfChaos.EffectUtils.Character.AllSkillsAgile; using RiskOfChaos.EffectUtils.Character.Player.Items; using RiskOfChaos.EffectUtils.World; using RiskOfChaos.EffectUtils.World.AllChanceShrines; using RiskOfChaos.EffectUtils.World.Items; using RiskOfChaos.EffectUtils.World.Spawn; using RiskOfChaos.ModCompatibility; using RiskOfChaos.ModificationController; using RiskOfChaos.ModificationController.AttackDelay; using RiskOfChaos.ModificationController.Camera; using RiskOfChaos.ModificationController.Cost; using RiskOfChaos.ModificationController.Director; using RiskOfChaos.ModificationController.Effect; using RiskOfChaos.ModificationController.Gravity; using RiskOfChaos.ModificationController.HoldoutZone; using RiskOfChaos.ModificationController.Knockback; using RiskOfChaos.ModificationController.Pickups; using RiskOfChaos.ModificationController.Projectile; using RiskOfChaos.ModificationController.SkillSlots; using RiskOfChaos.ModificationController.TimeScale; using RiskOfChaos.ModificationController.UI; using RiskOfChaos.Networking; using RiskOfChaos.Networking.Components; using RiskOfChaos.Networking.SyncList; using RiskOfChaos.PatcherInterop; using RiskOfChaos.Patches; using RiskOfChaos.Patches.AttackHooks; using RiskOfChaos.SaveHandling; using RiskOfChaos.SaveHandling.DataContainers; using RiskOfChaos.SaveHandling.DataContainers.EffectHandlerControllers; using RiskOfChaos.ScreenEffect; using RiskOfChaos.Serialization.Converters; using RiskOfChaos.Trackers; using RiskOfChaos.Twitch; using RiskOfChaos.UI.ActiveEffectsPanel; using RiskOfChaos.UI.ChatVoting; using RiskOfChaos.UI.NextEffectDisplay; using RiskOfChaos.Utilities; using RiskOfChaos.Utilities.Assets; using RiskOfChaos.Utilities.BodySnapshots; using RiskOfChaos.Utilities.Comparers; using RiskOfChaos.Utilities.DropTables; using RiskOfChaos.Utilities.Extensions; using RiskOfChaos.Utilities.Interpolation; using RiskOfChaos.Utilities.ParsedValueHolders; using RiskOfChaos.Utilities.PersistentSaveData; using RiskOfChaos.Utilities.Pickup; using RiskOfChaos.Utilities.Pool; using RiskOfChaos.Utilities.Reflection; using RiskOfOptions; using RiskOfOptions.OptionConfigs; using RiskOfOptions.Options; using RiskOfTwitch; using RiskOfTwitch.Chat.Message; using RiskOfTwitch.Chat.Notification; using RiskOfTwitch.EventSub; using RiskOfTwitch.Logging; using RiskOfTwitch.User; using RoR2; using RoR2.Artifacts; using RoR2.Audio; using RoR2.CameraModes; using RoR2.CharacterAI; using RoR2.ConVar; using RoR2.ContentManagement; using RoR2.EntitlementManagement; using RoR2.ExpansionManagement; using RoR2.Hologram; using RoR2.Items; using RoR2.Navigation; using RoR2.Networking; using RoR2.Orbs; using RoR2.Projectile; using RoR2.Skills; using RoR2.Stats; using RoR2.UI; using RoR2.UI.LogBook; using RoR2.UI.MainMenu; using RoR2.UI.SkinControllers; using RoR2BepInExPack.Utilities; using TMPro; using Unity; using UnityEngine; using UnityEngine.AddressableAssets; using UnityEngine.EventSystems; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.ResourceManagement.AsyncOperations; using UnityEngine.SceneManagement; using UnityEngine.UI; [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: NetworkCompatibility(/*Could not decode attribute arguments.*/)] [assembly: OptIn] [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyInformationalVersion("1.0.0+6e0465f6f074660b5b26433765a42c05415c18bb")] [assembly: AssemblyProduct("RiskOfChaos")] [assembly: AssemblyTitle("RiskOfChaos")] [assembly: AssemblyCompany("RiskOfChaos")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("2.0.0")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("2.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class ParamCollectionAttribute : Attribute { } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)] [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] 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; } } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)] [Microsoft.CodeAnalysis.Embedded] [CompilerGenerated] internal sealed class NullableContextAttribute : Attribute { public readonly byte Flag; public NullableContextAttribute(byte P_0) { Flag = P_0; } } [CompilerGenerated] [AttributeUsage(AttributeTargets.Parameter, AllowMultiple = false, Inherited = false)] [Microsoft.CodeAnalysis.Embedded] internal sealed class ScopedRefAttribute : Attribute { } [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } internal sealed class IsExternalInit { } } namespace RiskOfChaos { public static class Configs { public static class ChatVoting { public enum ChatVotingMode { Disabled, Twitch } [CompilerGenerated] private static class <>O { public static UnityAction <0>__AuthenticateNewToken; } [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static UnityAction <>9__12_1; internal void <Bind>b__12_1() { ChatVoting.OnReconnectButtonPressed?.Invoke(); } } public const string SECTION_NAME = "Streamer Integration"; public static readonly ConfigHolder<ChatVotingMode> VotingMode = ConfigFactory<ChatVotingMode>.CreateConfig("Voting Mode", ChatVotingMode.Disabled).OptionConfig((BaseOptionConfig)new ChoiceConfig()).Build(); public static readonly ConfigHolder<string> OverrideChannelName = ConfigFactory<string>.CreateConfig("Override Channel Name", string.Empty).Description("Used to specify a different channel the mod will connect to, leave empty to use the channel of the account that you authenticated with").OptionConfig((BaseOptionConfig)new InputFieldConfig { lineType = (LineType)0, richText = false, submitOn = (SubmitEnum)6, checkIfDisabled = new IsDisabledDelegate(isVotingDisabled) }) .Build(); private const int NUM_EFFECT_OPTIONS_MIN_VALUE = 2; public static readonly ConfigHolder<int> NumEffectOptions; public static readonly ConfigHolder<bool> IncludeRandomEffectInVote; public static readonly ConfigHolder<VoteWinnerSelectionMode> WinnerSelectionMode; public static event Action OnReconnectButtonPressed; [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool isVotingDisabled() { return VotingMode.Value == ChatVotingMode.Disabled; } internal static void Bind(ConfigFile file) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_0096: Unknown result type (might be due to invalid IL or missing references) //IL_00aa: Expected O, but got Unknown //IL_008b: Unknown result type (might be due to invalid IL or missing references) //IL_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0096: Expected O, but got Unknown bindConfig(VotingMode); object obj = <>O.<0>__AuthenticateNewToken; if (obj == null) { UnityAction val = TwitchAuthenticationManager.AuthenticateNewToken; <>O.<0>__AuthenticateNewToken = val; obj = (object)val; } ModSettingsManager.AddOption((BaseOption)new GenericButtonOption("Authenticate (Twitch)", "Streamer Integration", "Authenticate your account with Risk of Chaos (Opens browser tab)", "Open", (UnityAction)obj), "RoC_Config_General", "Risk of Chaos: General"); bindConfig(OverrideChannelName); object obj2 = <>c.<>9__12_1; if (obj2 == null) { UnityAction val2 = delegate { ChatVoting.OnReconnectButtonPressed?.Invoke(); }; <>c.<>9__12_1 = val2; obj2 = (object)val2; } ModSettingsManager.AddOption((BaseOption)new GenericButtonOption("Manual reconnect", "Streamer Integration", "Use this to manually reconnect the mod to your channel if connection is lost", "Reconnect", (UnityAction)obj2), "RoC_Config_General", "Risk of Chaos: General"); bindConfig(NumEffectOptions); bindConfig(IncludeRandomEffectInVote); bindConfig(WinnerSelectionMode); void bindConfig(ConfigHolderBase configHolder) { configHolder.Bind(file, "Streamer Integration", "RoC_Config_General", "Risk of Chaos: General"); } } static ChatVoting() { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0015: 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_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0044: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_0064: Expected O, but got Unknown //IL_0069: Expected O, but got Unknown //IL_0093: Unknown result type (might be due to invalid IL or missing references) //IL_0098: Unknown result type (might be due to invalid IL or missing references) //IL_009f: Expected O, but got Unknown //IL_009f: Unknown result type (might be due to invalid IL or missing references) //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Expected O, but got Unknown //IL_00b6: Expected O, but got Unknown //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_00da: Unknown result type (might be due to invalid IL or missing references) //IL_00e2: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Expected O, but got Unknown //IL_00f1: Expected O, but got Unknown //IL_0110: Unknown result type (might be due to invalid IL or missing references) //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0127: Expected O, but got Unknown //IL_012c: Expected O, but got Unknown ConfigFactory<int> configFactory = ConfigFactory<int>.CreateConfig("Num Effect Options", 3).Description("The number of effects viewers can pick from during voting").AcceptableValues((AcceptableValueBase)(object)new AcceptableValueMin<int>(2)); IntFieldConfig val = new IntFieldConfig(); ((NumericFieldConfig<int>)val).Min = 2; ((BaseOptionConfig)val).checkIfDisabled = new IsDisabledDelegate(isVotingDisabled); NumEffectOptions = configFactory.OptionConfig((BaseOptionConfig)val).Build(); IncludeRandomEffectInVote = ConfigFactory<bool>.CreateConfig("Include Random Effect In Vote", defaultValue: true).Description("If this is enabled, an additional option will be added to the effect vote list, which will activate a random effect instead of a specific one").OptionConfig((BaseOptionConfig)new CheckBoxConfig { checkIfDisabled = new IsDisabledDelegate(isVotingDisabled) }) .Build(); WinnerSelectionMode = ConfigFactory<VoteWinnerSelectionMode>.CreateConfig("Vote Winner Selection Mode", VoteWinnerSelectionMode.MostVotes).Description("How the winner of any vote should be selected.\r\n\r\nMostVotes (Default): The vote with the most votes will be selected, if there is a tie, a random tied option is selected\r\nRandomProportional: Every option has a chance to be selected, weighted by the number of votes. Ex. an option with 70% of the votes will have a 70% chance to be selected.").OptionConfig((BaseOptionConfig)new ChoiceConfig { checkIfDisabled = new IsDisabledDelegate(isVotingDisabled) }) .Build(); } } public static class ChatVotingUI { public enum VoteDisplayScalingMode { Disabled, Smooth, Immediate } public const string SECTION_NAME = "Streamer Integration: UI"; public static readonly ConfigHolder<float> VoteDisplayScaleMultiplier; public static readonly ConfigHolder<Color> VoteDisplayTextColor; public static readonly ConfigHolder<Color> VoteDisplayBackgroundColor; public static readonly ConfigHolder<VoteDisplayScalingMode> VoteDisplayScalingModeConfig; internal static void Bind(ConfigFile file) { bindConfig(VoteDisplayScaleMultiplier); bindConfig(VoteDisplayTextColor); bindConfig(VoteDisplayBackgroundColor); bindConfig(VoteDisplayScalingModeConfig); void bindConfig(ConfigHolderBase configHolder) { configHolder.Bind(file, "Streamer Integration: UI", "RoC_Config_General", "Risk of Chaos: General"); } } static ChatVotingUI() { //IL_0028: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected O, but got Unknown //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_0043: Expected O, but got Unknown //IL_0048: Expected O, but got Unknown //IL_0075: Unknown result type (might be due to invalid IL or missing references) //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0093: Expected O, but got Unknown //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00d4: Unknown result type (might be due to invalid IL or missing references) //IL_00de: Expected O, but got Unknown //IL_0107: Unknown result type (might be due to invalid IL or missing references) //IL_0111: Expected O, but got Unknown ConfigFactory<float> configFactory = ConfigFactory<float>.CreateConfig("Vote Display UI Scale", 1f).Description("The scale multiplier of the effect vote options display").AcceptableValues((AcceptableValueBase)(object)new AcceptableValueMin<float>(0f)); FloatFieldConfig val = new FloatFieldConfig(); ((NumericFieldConfig<float>)val).FormatString = "{0}X"; ((NumericFieldConfig<float>)val).Min = 0f; VoteDisplayScaleMultiplier = configFactory.OptionConfig((BaseOptionConfig)val).MovedFrom("Streamer Integration").Build(); VoteDisplayTextColor = ConfigFactory<Color>.CreateConfig("Vote Display Text Color", new Color(1f, 1f, 1f, 1f)).Description("The color of the effect voting options text").OptionConfig((BaseOptionConfig)new ColorOptionConfig()) .MovedFrom("Streamer Integration") .Build(); VoteDisplayBackgroundColor = ConfigFactory<Color>.CreateConfig("Vote Display Background Color", new Color(0.0943f, 0.0943f, 0.0943f, 0.3373f)).Description("The color of the effect voting options backdrop").OptionConfig((BaseOptionConfig)new ColorOptionConfig()) .MovedFrom("Streamer Integration") .Build(); VoteDisplayScalingModeConfig = ConfigFactory<VoteDisplayScalingMode>.CreateConfig("Vote Display Text Scaling Mode", VoteDisplayScalingMode.Smooth).Description("Controls how the vote options text will be scaled depending on how many votes that option has\r\n\r\nDisabled: No scaling is done, all options are always displayed exactly the same\r\n\r\nSmooth: Scaling is done, and interpolated to smoothly approach the target scale\r\n\r\nImmediate: Scaling is done, and applied immediately instead of smoothly interpolating").OptionConfig((BaseOptionConfig)new ChoiceConfig()) .Build(); } } public static class EffectSelection { [CompilerGenerated] private static class <>O { public static IsDisabledDelegate <0>__perStageEffectListDisabled; } public const string SECTION_NAME = "Effect Selection"; public static readonly ConfigHolder<bool> SeededEffectSelection = ConfigFactory<bool>.CreateConfig("Seeded Effect Selection", defaultValue: false).Description("If the effects should be consistent with the run seed, only really changes anything if you're setting run seeds manually").OptionConfig((BaseOptionConfig)new CheckBoxConfig()) .MovedFrom("General") .Build(); public static readonly ConfigHolder<bool> PerStageEffectListEnabled = ConfigFactory<bool>.CreateConfig("Per-Stage Effect List", defaultValue: false).Description("If enabled, a subsection of all effects is generated each stage and only effects from this list are activated.\r\nNot supported in any chat voting mode").OptionConfig((BaseOptionConfig)new CheckBoxConfig()) .Build(); public static ConfigHolder<int> PerStageEffectListSize { get; private set; } [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool perStageEffectListDisabled() { return !PerStageEffectListEnabled.Value; } internal static void Bind(ConfigFile file) { bindConfig(SeededEffectSelection); bindConfig(PerStageEffectListEnabled); ((ResourceAvailability)(ref ChaosEffectCatalog.Availability)).CallWhenAvailable((Action)delegate { //IL_0032: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Unknown result type (might be due to invalid IL or missing references) //IL_003e: 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_006f: Expected O, but got Unknown //IL_005a: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) //IL_0065: Expected O, but got Unknown ConfigFactory<int> configFactory = ConfigFactory<int>.CreateConfig("Effect List Size", Math.Min(50, ChaosEffectCatalog.EffectCount / 2)).Description("The size of the per-stage effect list\r\nNot supported in any chat voting mode").AcceptableValues((AcceptableValueBase)(object)new AcceptableValueRange<int>(1, ChaosEffectCatalog.EffectCount)); IntSliderConfig val = new IntSliderConfig { min = 1, max = ChaosEffectCatalog.EffectCount }; object obj = <>O.<0>__perStageEffectListDisabled; if (obj == null) { IsDisabledDelegate val2 = perStageEffectListDisabled; <>O.<0>__perStageEffectListDisabled = val2; obj = (object)val2; } ((BaseOptionConfig)val).checkIfDisabled = (IsDisabledDelegate)obj; PerStageEffectListSize = configFactory.OptionConfig((BaseOptionConfig)val).Build(); bindConfig(PerStageEffectListSize); }); void bindConfig(ConfigHolderBase config) { config.Bind(file, "Effect Selection", "RoC_Config_General", "Risk of Chaos: General"); } } } public static class General { public const string SECTION_NAME = "General"; public static readonly ConfigHolder<bool> DisableEffectDispatching = ConfigFactory<bool>.CreateConfig("Disable Effect Activation", defaultValue: false).Description("If timer-based effect activation should be disabled completely").OptionConfig((BaseOptionConfig)new CheckBoxConfig()) .Networked() .Build(); private const float TIME_BETWEEN_EFFECTS_MIN_VALUE = 5f; public static readonly ConfigHolder<float> TimeBetweenEffects; public static readonly ConfigHolder<bool> RunEffectsTimerWhileRunTimerPaused; [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool effectDispatchingDisabled() { return DisableEffectDispatching.LocalValue; } internal static void Bind(ConfigFile file) { bindConfig(DisableEffectDispatching); bindConfig(TimeBetweenEffects); bindConfig(RunEffectsTimerWhileRunTimerPaused); void bindConfig(ConfigHolderBase config) { config.Bind(file, "General", "RoC_Config_General", "Risk of Chaos: General"); } } static General() { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Expected O, but got Unknown //IL_0056: 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_0066: Expected O, but got Unknown //IL_0066: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_0071: 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_0083: Expected O, but got Unknown //IL_0088: Expected O, but got Unknown //IL_00a7: Unknown result type (might be due to invalid IL or missing references) //IL_00ac: Unknown result type (might be due to invalid IL or missing references) //IL_00b4: Unknown result type (might be due to invalid IL or missing references) //IL_00be: Expected O, but got Unknown //IL_00c3: Expected O, but got Unknown ConfigFactory<float> configFactory = ConfigFactory<float>.CreateConfig("Effect Timer", 60f).Description("How often new effects should happen").AcceptableValues((AcceptableValueBase)(object)new AcceptableValueMin<float>(5f)); FloatFieldConfig val = new FloatFieldConfig(); ((NumericFieldConfig<float>)val).FormatString = "{0}s"; ((NumericFieldConfig<float>)val).Min = 5f; ((BaseOptionConfig)val).checkIfDisabled = new IsDisabledDelegate(effectDispatchingDisabled); TimeBetweenEffects = configFactory.OptionConfig((BaseOptionConfig)val).Build(); RunEffectsTimerWhileRunTimerPaused = ConfigFactory<bool>.CreateConfig("Dispatch Effects While Timer Paused", defaultValue: true).Description("If the mod should activate effects while the run timer is paused (in Bazaar, Gilded Coast, etc.)").OptionConfig((BaseOptionConfig)new CheckBoxConfig { checkIfDisabled = new IsDisabledDelegate(effectDispatchingDisabled) }) .Networked() .Build(); } } internal static class Metadata { public const string SECTION_NAME = "META"; public const uint CONFIG_FILE_VERSION_LEGACY = 0u; public const uint CURRENT_CONFIG_FILE_VERSION = 20u; public static readonly ConfigHolder<uint> ConfigFileVersion = ConfigFactory<uint>.CreateConfig("VERSION", 0u).Description("Used internally by the mod\r\nDO NOT MODIFY MANUALLY").Build(); internal static void Bind(ConfigFile file) { bindConfig(ConfigFileVersion); void bindConfig(ConfigHolderBase config) { config.Bind(file, "META", "RoC_Config_General", "Risk of Chaos: General"); } } private static bool isOutdatedVersion() { if (ConfigFileVersion.Value < 20) { return ConfigManager.AllConfigs.Any((ConfigHolderBase c) => !c.IsDefaultValue); } return false; } internal static void CheckVersion() { if (isOutdatedVersion()) { PopupAlertQueue.EnqueueAlert(delegate(SimpleDialogBox dialogBox) { //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) dialogBox.headerToken = new TokenParamsPair("POPUP_CONFIG_UPDATE_HEADER", Array.Empty<object>()); dialogBox.descriptionToken = new TokenParamsPair("POPUP_CONFIG_UPDATE_DESCRIPTION", Array.Empty<object>()); dialogBox.AddCommandButton("roc_delete_config", "POPUP_CONFIG_UPDATE_RESET", Array.Empty<object>()); dialogBox.AddCancelButton("POPUP_CONFIG_UPDATE_IGNORE", Array.Empty<object>()); }); } ConfigFileVersion.LocalValue = 20u; } } public static class UI { public enum NextEffectTimerDisplayType : byte { Never, WhenRunTimerUnavailable, Always } public const string SECTION_NAME = "UI"; public static readonly ConfigHolder<bool> HideActiveEffectsPanel = ConfigFactory<bool>.CreateConfig("Hide Active Effects Panel", defaultValue: false).Description("Hides the active effects list under the Objectives display").OptionConfig((BaseOptionConfig)new CheckBoxConfig()) .Build(); public static readonly ConfigHolder<bool> DisplayAlwaysActiveEffects = ConfigFactory<bool>.CreateConfig("Display Permanently Active Effects", defaultValue: false).Description("If effects configured to always be active should be displayed in the active effects panel").OptionConfig((BaseOptionConfig)new CheckBoxConfig { checkIfDisabled = new IsDisabledDelegate(activeEffectsPanelHidden) }) .Build(); public static readonly ConfigHolder<Color> ActiveEffectsTextColor = ConfigFactory<Color>.CreateConfig("Active Effect Text Color", Color.white).Description("The color of the effect names in the \"Active Effects\" list").OptionConfig((BaseOptionConfig)new ColorOptionConfig { checkIfDisabled = new IsDisabledDelegate(activeEffectsPanelHidden) }) .MovedFrom("General") .Build(); public static readonly ConfigHolder<bool> DisplayNextEffect = ConfigFactory<bool>.CreateConfig("Display Next Effect", defaultValue: true).Description("Displays the next effect that will happen.\r\nOnly works if chat voting is disabled and seeded mode is enabled").OptionConfig((BaseOptionConfig)new CheckBoxConfig()) .Build(); public static readonly ConfigHolder<NextEffectTimerDisplayType> NextEffectTimerDisplayMode = ConfigFactory<NextEffectTimerDisplayType>.CreateConfig("Next Effect Timer Display Mode", NextEffectTimerDisplayType.WhenRunTimerUnavailable).Description("Displays how much time is left until the next effect.\r\n\r\nNever: The time remaining is never displayed.\r\nWhenRunTimerUnavailable: Displays time remaining only when the regular run timer is paused or otherwise not visible.\r\nAlways: Time remaining is always displayed").OptionConfig((BaseOptionConfig)new ChoiceConfig()) .Build(); [MethodImpl(MethodImplOptions.AggressiveInlining)] private static bool activeEffectsPanelHidden() { return HideActiveEffectsPanel.Value; } public static bool ShouldShowNextEffectTimer(HUD hud) { switch (NextEffectTimerDisplayMode.Value) { case NextEffectTimerDisplayType.Never: return false; case NextEffectTimerDisplayType.WhenRunTimerUnavailable: { Run instance = Run.instance; if (Object.op_Implicit((Object)(object)instance)) { if (!instance.isRunStopwatchPaused || !General.RunEffectsTimerWhileRunTimerPaused.Value) { return !RunTimerUITracker.IsAnyTimerVisibleForHUD(hud); } return true; } return false; } case NextEffectTimerDisplayType.Always: return true; default: throw new NotImplementedException(); } } internal static void Bind(ConfigFile file) { bindConfig(HideActiveEffectsPanel); bindConfig(DisplayAlwaysActiveEffects); bindConfig(ActiveEffectsTextColor); bindConfig(DisplayNextEffect); bindConfig(NextEffectTimerDisplayMode); void bindConfig(ConfigHolderBase config) { config.Bind(file, "UI", "RoC_Config_General", "Risk of Chaos: General"); } } } private const string CONFIG_GUID = "RoC_Config_General"; private const string CONFIG_NAME = "Risk of Chaos: General"; public static Sprite GenericIcon { get; private set; } private static FileInfo findFileInParentDirectories(DirectoryInfo startDir, string searchPattern) { DirectoryInfo directoryInfo = startDir; while (directoryInfo != null && !string.Equals(directoryInfo.FullName, Paths.PluginPath, StringComparison.OrdinalIgnoreCase)) { FileInfo fileInfo = directoryInfo.EnumerateFiles(searchPattern, SearchOption.TopDirectoryOnly).FirstOrDefault(); if (fileInfo != null) { return fileInfo; } directoryInfo = directoryInfo.Parent; } return null; } private static Sprite generateIcon() { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Expected O, but got Unknown //IL_0069: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) FileInfo fileInfo = findFileInParentDirectories(new DirectoryInfo(RiskOfChaosPlugin.ModDirectory), "icon.png"); if (fileInfo == null) { return null; } Texture2D val = new Texture2D(256, 256); ((Object)val).name = "texRiskOfChaosIcon"; if (!ImageConversion.LoadImage(val, File.ReadAllBytes(fileInfo.FullName))) { Object.Destroy((Object)(object)val); return null; } Sprite obj = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f)); ((Object)obj).name = "RiskOfChaosIcon"; return obj; } internal static void Init(ConfigFile file) { General.Bind(file); EffectSelection.Bind(file); UI.Bind(file); ChatVoting.Bind(file); ChatVotingUI.Bind(file); Metadata.Bind(file); if (!Object.op_Implicit((Object)(object)GenericIcon)) { GenericIcon = generateIcon(); } if (Object.op_Implicit((Object)(object)GenericIcon)) { ModSettingsManager.SetModIcon(GenericIcon, "RoC_Config_General", "Risk of Chaos: General"); } ModSettingsManager.SetModDescription("General config options for Risk of Chaos", "RoC_Config_General", "Risk of Chaos: General"); } } internal static class LanguageFileHandler { internal static void Init() { Language.collectLanguageRootFolders += delegate(List<string> folders) { string text = Path.Combine(RiskOfChaosPlugin.ModDirectory, "lang"); if (Directory.Exists(text)) { folders.Add(text); } else { Log.Warning("Unable to find lang folder at " + text, "D:\\Git\\RiskOfChaos\\Solution\\RiskOfChaos\\LanguageFileHandler.cs", "Init", 20); } }; } } internal static class Log { private static readonly object _stringBuilderLock; private static readonly StringBuilder _sharedStringBuilder; private static readonly int _cachedCallerPathPrefixLength; private static ManualLogSource _logSource; static Log() { _stringBuilderLock = new object(); _sharedStringBuilder = new StringBuilder(256); _cachedCallerPathPrefixLength = getCallerPathPrefixLength("D:\\Git\\RiskOfChaos\\Solution\\RiskOfChaos\\Log.cs"); static int getCallerPathPrefixLength([CallerFilePath] string callerPath = null) { int num = callerPath.LastIndexOf("RiskOfChaos\\"); if (num >= 0) { return num + "RiskOfChaos\\".Length; } Debug.LogError((object)"[RiskOfChaos] Logger failed to determine caller path prefix length"); return 0; } } internal static void Init(ManualLogSource logSource) { _logSource = logSource; } private static StringBuilder AppendCallerPrefix(this StringBuilder stringBuilder, string callerPath, string callerMemberName, int callerLineNumber) { return stringBuilder.Append(callerPath, _cachedCallerPathPrefixLength, callerPath.Length - _cachedCallerPathPrefixLength).Append(':').Append(callerLineNumber) .Append(" (") .Append(callerMemberName) .Append("):"); } private static StringBuilder buildCallerLogString(string callerPath, string callerMemberName, int callerLineNumber, object data) { lock (_stringBuilderLock) { return _sharedStringBuilder.Clear().AppendCallerPrefix(callerPath, callerMemberName, callerLineNumber).Append(' ') .Append(data); } } [Conditional("DEBUG")] internal static void Debug(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { _logSource.LogDebug((object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [Conditional("DEBUG")] internal static void Debug_NoCallerPrefix(object data) { _logSource.LogDebug(data); } internal static void Error(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { _logSource.LogError((object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Error_NoCallerPrefix(object data) { _logSource.LogError(data); } internal static void Fatal(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { _logSource.LogFatal((object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Fatal_NoCallerPrefix(object data) { _logSource.LogFatal(data); } internal static void Info(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { _logSource.LogInfo((object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Info_NoCallerPrefix(object data) { _logSource.LogInfo(data); } internal static void Message(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { _logSource.LogMessage((object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Message_NoCallerPrefix(object data) { _logSource.LogMessage(data); } internal static void Warning(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { _logSource.LogWarning((object)buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Warning_NoCallerPrefix(object data) { _logSource.LogWarning(data); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static bool ShouldLog(LogLevel logLevel) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 if ((logLevel & 0x20) != 0) { return false; } return (int)logLevel > 0; } internal static void LogType(LogLevel logLevel, object data) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_000e: Unknown result type (might be due to invalid IL or missing references) if (ShouldLog(logLevel)) { _logSource.Log(logLevel, data); } } } internal static class MidRunArtifactsHandler { [CompilerGenerated] private static class <>O { public static ArtifactStateChangeDelegate <0>__RunArtifactManager_onArtifactEnabledGlobal; public static ArtifactStateChangeDelegate <1>__RunArtifactManager_onArtifactDisabledGlobal; } [SystemInitializer(new Type[] { })] private static void Init() { //IL_0010: Unknown result type (might be due to invalid IL or missing references) //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Expected O, but got Unknown //IL_0030: 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_003b: Expected O, but got Unknown object obj = <>O.<0>__RunArtifactManager_onArtifactEnabledGlobal; if (obj == null) { ArtifactStateChangeDelegate val = RunArtifactManager_onArtifactEnabledGlobal; <>O.<0>__RunArtifactManager_onArtifactEnabledGlobal = val; obj = (object)val; } RunArtifactManager.onArtifactEnabledGlobal += (ArtifactStateChangeDelegate)obj; object obj2 = <>O.<1>__RunArtifactManager_onArtifactDisabledGlobal; if (obj2 == null) { ArtifactStateChangeDelegate val2 = RunArtifactManager_onArtifactDisabledGlobal; <>O.<1>__RunArtifactManager_onArtifactDisabledGlobal = val2; obj2 = (object)val2; } RunArtifactManager.onArtifactDisabledGlobal += (ArtifactStateChangeDelegate)obj2; } private static void RunArtifactManager_onArtifactEnabledGlobal(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) { onArtifactStateChanged(artifactDef, enabled: true); } private static void RunArtifactManager_onArtifactDisabledGlobal(RunArtifactManager runArtifactManager, ArtifactDef artifactDef) { onArtifactStateChanged(artifactDef, enabled: false); } private static void onArtifactStateChanged(ArtifactDef artifactDef, bool enabled) { if (!Object.op_Implicit((Object)(object)Stage.instance)) { return; } if (enabled) { foreach (LocalUser readOnlyLocalUsers in LocalUserManager.readOnlyLocalUsersList) { if (readOnlyLocalUsers != null) { CharacterMaster cachedMaster = readOnlyLocalUsers.cachedMaster; if (Object.op_Implicit((Object)(object)cachedMaster)) { CharacterMasterNotificationQueue.PushArtifactNotification(cachedMaster, artifactDef); } } } } if ((Object)(object)artifactDef == (Object)(object)Artifacts.Sacrifice) { if (enabled) { onSacrificeEnabled(); } } else if ((Object)(object)artifactDef == (Object)(object)Artifacts.RandomSurvivorOnRespawn) { if (enabled) { onMetamorphosisEnabled(); } } else if ((Object)(object)artifactDef == (Object)(object)Artifacts.SingleMonsterType) { if (!enabled) { onKinDisabled(); } } else if ((Object)(object)artifactDef == (Object)(object)Artifacts.Enigma) { if (enabled) { onEnigmaEnabled(); } } else if ((Object)(object)artifactDef == (Object)(object)Artifacts.Devotion) { if (enabled) { onDevotionEnabled(); } } else if ((Object)(object)artifactDef == (Object)(object)Artifacts.Delusion) { onDelusionEnabledOrDisabled(enabled); } else if ((Object)(object)artifactDef == (Object)(object)Artifacts.Rebirth && enabled) { onRebirthEnabled(); } CharacterBodyUtils.MarkAllBodyStatsDirty(); } private static void onKinDisabled() { if (NetworkServer.active && Object.op_Implicit((Object)(object)Stage.instance)) { Stage.instance.singleMonsterTypeBodyIndex = (BodyIndex)(-1); } } private static void onSacrificeEnabled() { if (!NetworkServer.active) { return; } List<ObjectSpawnCardTracker> instancesList = InstanceTracker.GetInstancesList<ObjectSpawnCardTracker>(); for (int num = instancesList.Count - 1; num >= 0; num--) { ObjectSpawnCardTracker objectSpawnCardTracker = instancesList[num]; if (Object.op_Implicit((Object)(object)objectSpawnCardTracker)) { SpawnCard spawnCard = objectSpawnCardTracker.SpawnCard; InteractableSpawnCard val = (InteractableSpawnCard)(object)((spawnCard is InteractableSpawnCard) ? spawnCard : null); if (val != null && val.skipSpawnWhenSacrificeArtifactEnabled) { NetworkServer.Destroy(((Component)objectSpawnCardTracker).gameObject); } } } } private static void onMetamorphosisEnabled() { if (!NetworkServer.active) { return; } foreach (CharacterBody allPlayerBody in PlayerUtils.GetAllPlayerBodies(requireAlive: true)) { allPlayerBody.master.Respawn(CharacterRespawnFlags.KeepState); } } private static void onEnigmaEnabled() { if (!NetworkServer.active) { return; } foreach (CharacterBody allPlayerBody in PlayerUtils.GetAllPlayerBodies(requireAlive: true)) { EnigmaArtifactManager.OnPlayerCharacterBodyStartServer(allPlayerBody); } } private static void onDevotionEnabled() { //IL_004b: Unknown result type (might be due to invalid IL or missing references) //IL_0050: Unknown result type (might be due to invalid IL or missing references) //IL_0056: 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_006a: Expected O, but got Unknown //IL_009e: Unknown result type (might be due to invalid IL or missing references) //IL_00a4: Expected O, but got Unknown //IL_00e7: Unknown result type (might be due to invalid IL or missing references) //IL_00ec: Unknown result type (might be due to invalid IL or missing references) //IL_00ee: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0102: Expected O, but got Unknown //IL_010b: Unknown result type (might be due to invalid IL or missing references) //IL_0112: Expected O, but got Unknown //IL_0120: Unknown result type (might be due to invalid IL or missing references) //IL_012c: Unknown result type (might be due to invalid IL or missing references) //IL_0133: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active) { return; } SceneDirector val = null; if (Object.op_Implicit((Object)(object)DirectorCore.instance)) { val = ((Component)DirectorCore.instance).GetComponent<SceneDirector>(); } DirectorCard val2; if (Object.op_Implicit((Object)(object)val)) { val2 = val.lumerianEgg; } else { Log.Warning("Failed to find SceneDirector", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfChaos\\MidRunArtifactsHandler.cs", "onDevotionEnabled", 175); val2 = new DirectorCard { spawnCard = (SpawnCard)(object)AddressableUtil.LoadTempAssetAsync<InteractableSpawnCard>("234cc71a82b0e82468900be4c544c1c8").WaitForCompletion() }; } if (val2 == null || !Object.op_Implicit((Object)(object)val2.spawnCard)) { Log.Error("Failed to find valid egg spawn card", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfChaos\\MidRunArtifactsHandler.cs", "onDevotionEnabled", 185); return; } Xoroshiro128Plus val3 = new Xoroshiro128Plus(RoR2Application.rng.nextUlong); List<ObjectSpawnCardTracker> instancesList = InstanceTracker.GetInstancesList<ObjectSpawnCardTracker>(); for (int num = instancesList.Count - 1; num >= 0; num--) { ObjectSpawnCardTracker objectSpawnCardTracker = instancesList[num]; if (Object.op_Implicit((Object)(object)objectSpawnCardTracker)) { SpawnCard spawnCard = objectSpawnCardTracker.SpawnCard; InteractableSpawnCard val4 = (InteractableSpawnCard)(object)((spawnCard is InteractableSpawnCard) ? spawnCard : null); if (val4 != null && val4.skipSpawnWhenDevotionArtifactEnabled) { DirectorPlacementRule val5 = new DirectorPlacementRule { placementMode = (PlacementMode)0, spawnOnTarget = ((Component)objectSpawnCardTracker).transform }; DirectorSpawnRequest val6 = new DirectorSpawnRequest(val2.spawnCard, val5, val3); val6.spawnCard.DoSpawn(((Component)objectSpawnCardTracker).transform.position, ((Component)objectSpawnCardTracker).transform.rotation, val6); NetworkServer.Destroy(((Component)objectSpawnCardTracker).gameObject); } } } } private static void onDelusionEnabledOrDisabled(bool enabled) { //IL_005d: 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_0074: Unknown result type (might be due to invalid IL or missing references) //IL_00e6: Unknown result type (might be due to invalid IL or missing references) //IL_00f0: Expected O, but got Unknown TeleporterInteraction instance = TeleporterInteraction.instance; bool flag = Object.op_Implicit((Object)(object)instance) && instance.isCharged; EntityStateMachine val2 = default(EntityStateMachine); foreach (DelusionChestControllerTracker instances in InstanceTracker.GetInstancesList<DelusionChestControllerTracker>()) { DelusionChestController delusionChestController = instances.DelusionChestController; if (!Object.op_Implicit((Object)(object)delusionChestController)) { continue; } if (enabled) { if (!delusionChestController.hasBeenReset) { ((Behaviour)delusionChestController).enabled = true; PickupIndex val = instances.TakePendingDelusionPickupIndex(); if (((PickupIndex)(ref val)).isValid) { delusionChestController.delusionChest.CallRpcSetDelusionPickupIndex(val); } if (flag) { delusionChestController.delusionChest.CallRpcResetChests(); } } } else if (delusionChestController.hasBeenReset) { ((Behaviour)delusionChestController).enabled = false; NetworkUIPromptController netUIPromptController = delusionChestController._netUIPromptController; if (Object.op_Implicit((Object)(object)netUIPromptController)) { ((Behaviour)netUIPromptController).enabled = false; } PickupPickerController pickupPickerController = delusionChestController._pickupPickerController; if (Object.op_Implicit((Object)(object)pickupPickerController)) { ((Behaviour)pickupPickerController).enabled = false; pickupPickerController.SetAvailable(false); } if (((Component)delusionChestController).TryGetComponent<EntityStateMachine>(ref val2)) { val2.SetNextState((EntityState)new Opening()); } } } } private static void onRebirthEnabled() { if (NetworkServer.active && Object.op_Implicit((Object)(object)Run.instance)) { Run.instance.ServerGiveRebirthItems(); } if (!NetworkClient.active) { return; } foreach (NetworkUser readOnlyInstances in NetworkUser.readOnlyInstancesList) { if (((NetworkBehaviour)readOnlyInstances).isLocalPlayer) { LocalUser localUser = readOnlyInstances.localUser; UserProfile val = ((localUser != null) ? localUser.userProfile : null); if (val != null && !string.IsNullOrEmpty(val.RebirthItem)) { val.RebirthItem = null; val.RequestEventualSave(); } } } } } [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInPlugin("Gorakh.RiskOfChaos", "RiskOfChaos", "2.7.1")] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] [BepInDependency(/*Could not decode attribute arguments.*/)] public sealed class RiskOfChaosPlugin : BaseUnityPlugin { public const string PluginGUID = "Gorakh.RiskOfChaos"; public const string PluginAuthor = "Gorakh"; public const string PluginName = "RiskOfChaos"; public const string PluginVersion = "2.7.1"; private Harmony _harmonyInstance; private static RiskOfChaosPlugin _instance; public static RiskOfChaosPlugin Instance => _instance; public static string ModDirectory { get; private set; } public RoCContent ContentPackProvider { get; private set; } private void Awake() { //IL_007c: Unknown result type (might be due to invalid IL or missing references) //IL_0086: Expected O, but got Unknown SingletonHelper.Assign<RiskOfChaosPlugin>(ref _instance, this); Stopwatch stopwatch = Stopwatch.StartNew(); Log.Init(((BaseUnityPlugin)this).Logger); TaskExceptionHandler.Initialize(); Log.LogSource = (ILogSource)(object)new TwitchLibLogSource(); ModDirectory = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location); ContentPackProvider = new RoCContent(); ContentPackProvider.Register(); LanguageFileHandler.Init(); NetworkMessageManager.RegisterMessages(); AdditionalResourceAvailability.InitHooks(); if (ProperSaveCompat.Active) { ProperSaveCompat.Init(); } ProcTypeAPICompat.Init(); _harmonyInstance = new Harmony("com.Gorakh.RiskOfChaos"); _harmonyInstance.PatchAll(Assembly.GetExecutingAssembly()); initConfigs(); Log.Message_NoCallerPrefix($"Initialized in {stopwatch.Elapsed.TotalSeconds:F2} seconds"); stopwatch.Stop(); } private void initConfigs() { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = false; Configs.Init(((BaseUnityPlugin)this).Config); ChaosEffectCatalog.InitConfig(((BaseUnityPlugin)this).Config); RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, (Action)delegate { ((BaseUnityPlugin)this).Config.SaveOnConfigSet = true; ((BaseUnityPlugin)this).Config.Save(); Configs.Metadata.CheckVersion(); }); } private void OnDestroy() { SingletonHelper.Unassign<RiskOfChaosPlugin>(ref _instance, this); TaskExceptionHandler.Cleanup(); if (ProperSaveCompat.Active) { ProperSaveCompat.Cleanup(); } Harmony harmonyInstance = _harmonyInstance; if (harmonyInstance != null) { harmonyInstance.UnpatchSelf(); } } } internal sealed class TwitchLibLogSource : ILogSource { public void Log(object message, LogType type) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_001e: Expected I4, but got Unknown //IL_0022: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Unknown result type (might be due to invalid IL or missing references) //IL_002b: Unknown result type (might be due to invalid IL or missing references) //IL_002f: 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_0037: Unknown result type (might be due to invalid IL or missing references) //IL_0050: 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) RiskOfChaos.Log.LogType((LogLevel)((int)type switch { 0 => 32, 1 => 16, 2 => 8, 3 => 4, 4 => 2, 5 => 1, _ => throw new NotImplementedException($"Log type {type} is not implemented"), }), message); } } } namespace RiskOfChaos.Utilities { public static class AdditionalResourceAvailability { [Serializable] [CompilerGenerated] private sealed class <>c { public static readonly <>c <>9 = new <>c(); public static hook_Init <>9__3_0; public static hook_Init <>9__3_1; public static hook_SetEntries <>9__3_2; internal void <InitHooks>b__3_0(orig_Init orig) { orig.Invoke(); ((ResourceAvailability)(ref BuffCatalog)).MakeAvailable(); } internal void <InitHooks>b__3_1(orig_Init orig) { orig.Invoke(); ((ResourceAvailability)(ref MasterCatalog)).MakeAvailable(); } internal void <InitHooks>b__3_2(orig_SetEntries orig, PickupDef[] entries) { orig.Invoke(entries); ((ResourceAvailability)(ref PickupCatalog)).MakeAvailable(); } } public static ResourceAvailability BuffCatalog; public static ResourceAvailability MasterCatalog; public static ResourceAvailability PickupCatalog; internal static void InitHooks() { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001f: 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_005c: 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_0067: Expected O, but got Unknown object obj = <>c.<>9__3_0; if (obj == null) { hook_Init val = delegate(orig_Init orig) { orig.Invoke(); ((ResourceAvailability)(ref BuffCatalog)).MakeAvailable(); }; <>c.<>9__3_0 = val; obj = (object)val; } BuffCatalog.Init += (hook_Init)obj; object obj2 = <>c.<>9__3_1; if (obj2 == null) { hook_Init val2 = delegate(orig_Init orig) { orig.Invoke(); ((ResourceAvailability)(ref MasterCatalog)).MakeAvailable(); }; <>c.<>9__3_1 = val2; obj2 = (object)val2; } MasterCatalog.Init += (hook_Init)obj2; object obj3 = <>c.<>9__3_2; if (obj3 == null) { hook_SetEntries val3 = delegate(orig_SetEntries orig, PickupDef[] entries) { orig.Invoke(entries); ((ResourceAvailability)(ref PickupCatalog)).MakeAvailable(); }; <>c.<>9__3_2 = val3; obj3 = (object)val3; } PickupCatalog.SetEntries += (hook_SetEntries)obj3; } } public static class AddressableUtil { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static AsyncOperationHandle<T> LoadAssetAsync<T>(string assetGuid, AsyncReferenceHandleUnloadType unloadType = 2) where T : Object { //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) return AssetAsyncReferenceManager<T>.LoadAsset(new AssetReferenceT<T>(assetGuid), unloadType); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static AsyncOperationHandle<T> LoadAssetAsync<T>(AssetReferenceT<T> assetReference, AsyncReferenceHandleUnloadType unloadType = 2) where T : Object { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) return AssetAsyncReferenceManager<T>.LoadAsset(assetReference, unloadType); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static AsyncOperationHandle<T> LoadTempAssetAsync<T>(string assetGuid) where T : Object { //IL_0006: Unknown result type (might be due to invalid IL or missing references) return LoadTempAssetAsync<T>(new AssetReferenceT<T>(assetGuid)); } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static AsyncOperationHandle<T> LoadTempAssetAsync<T>(AssetReferenceT<T> assetReference) where T : Object { //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) AsyncOperationHandle<T> result = AssetAsyncReferenceManager<T>.LoadAsset(assetReference, (AsyncReferenceHandleUnloadType)2); result.Completed += delegate { AssetAsyncReferenceManager<T>.UnloadAsset(assetReference); }; return result; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static void UnloadAsset<T>(AssetReferenceT<T> assetReference) where T : Object { AssetAsyncReferenceManager<T>.UnloadAsset(assetReference); } } public readonly struct AsyncOperationCoroutineProgressReporter : IEnumerator { private readonly IAsyncOperationCoroutine _coroutine; private readonly IProgress<float> _progressReceiver; object IEnumerator.Current => _coroutine.Current; public AsyncOperationCoroutineProgressReporter(IAsyncOperationCoroutine asyncOperationHandle, IProgress<float> progressReceiver) { _coroutine = asyncOperationHandle; _progressReceiver = progressReceiver; } bool IEnumerator.MoveNext() { _progressReceiver.Report(_coroutine.Progress); return _coroutine.MoveNext(); } void IEnumerator.Reset() { _coroutine.Reset(); } } public readonly struct AsyncOperationCoroutineWrapper : IAsyncOperationCoroutine, IEnumerator { private readonly AsyncOperationHandle _asyncOperationHandle; public float Progress { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) AsyncOperationHandle asyncOperationHandle = _asyncOperationHandle; return ((AsyncOperationHandle)(ref asyncOperationHandle)).PercentComplete; } } object IEnumerator.Current => ((IEnumerator)_asyncOperationHandle).Current; public AsyncOperationCoroutineWrapper(AsyncOperationHandle asyncOperationHandle) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) _asyncOperationHandle = asyncOperationHandle; } bool IEnumerator.MoveNext() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return ((IEnumerator)_asyncOperationHandle).MoveNext(); } void IEnumerator.Reset() { //IL_0001: Unknown result type (might be due to invalid IL or missing references) ((IEnumerator)_asyncOperationHandle).Reset(); } } public static class AttackUtils { public static BulletAttack Clone(BulletAttack src) { return src?.ShallowCopy<BulletAttack>(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } public static BlastAttack Clone(BlastAttack src) { return src?.ShallowCopy<BlastAttack>(); } public static OverlapAttack Clone(OverlapAttack src) { return src?.ShallowCopy<OverlapAttack>(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); } } public readonly record struct BodySkillPair(BodyIndex BodyIndex, SkillSlot SkillSlot) { public BodySkillPair(BodyIndex BodyIndex, SkillSlot SkillSlot) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Unknown result type (might be due to invalid IL or missing references) this.BodyIndex = BodyIndex; this.SkillSlot = SkillSlot; } public BodySkillPair(string bodyName, SkillSlot slot) : this(BodyCatalog.FindBodyIndex(bodyName), slot) { }//IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) [CompilerGenerated] private bool PrintMembers(StringBuilder builder) { //IL_000e: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Unknown result type (might be due to invalid IL or missing references) //IL_003a: Unknown result type (might be due to invalid IL or missing references) builder.Append("BodyIndex = "); BodyIndex bodyIndex = BodyIndex; builder.Append(((object)(BodyIndex)(ref bodyIndex)).ToString()); builder.Append(", SkillSlot = "); SkillSlot skillSlot = SkillSlot; builder.Append(((object)(SkillSlot)(ref skillSlot)).ToString()); return true; } [CompilerGenerated] public void Deconstruct(out BodyIndex BodyIndex, out SkillSlot SkillSlot) { //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Expected I4, but got Unknown //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected I4, but got Unknown BodyIndex = (BodyIndex)(int)this.BodyIndex; SkillSlot = (SkillSlot)(int)this.SkillSlot; } } public static class BossUtils { public static void TryRefreshBossTitleFor(CharacterMaster master) { if (Object.op_Implicit((Object)(object)master)) { CharacterBody body = master.GetBody(); if (Object.op_Implicit((Object)(object)body)) { TryRefreshBossTitleFor(body); } } } public static void TryRefreshBossTitleFor(CharacterBody characterBody) { BossGroup val = BossGroup.FindBossGroup(characterBody); if (Object.op_Implicit((Object)(object)val)) { RefreshBossTitle(val); } } public static void RefreshBossTitle(BossGroup bossGroup) { bossGroup.bestObservedName = string.Empty; bossGroup.bestObservedSubtitle = string.Empty; } } public static class BuffUtils { private static string[] _buffNameTokenLookup = Array.Empty<string>(); [SystemInitializer(new Type[] { typeof(BuffCatalog) })] private static void Init() { _buffNameTokenLookup = new string[BuffCatalog.buffCount]; Array.Fill(_buffNameTokenLookup, string.Empty); StringBuilder stringBuilder = StringBuilderPool.RentStringBuilder(); for (int i = 0; i < BuffCatalog.buffCount; i++) { BuffDef buffDef = BuffCatalog.GetBuffDef((BuffIndex)i); if (!Object.op_Implicit((Object)(object)buffDef)) { continue; } string name = ((Object)buffDef).name; if (string.IsNullOrWhiteSpace(name)) { continue; } name = name.Trim(); int num = 0; if (name.StartsWith("bd")) { num += 2; } stringBuilder.Clear(); stringBuilder.EnsureCapacity(name.Length + 15); stringBuilder.Append("ROC_BUFF_"); for (int j = num; j < name.Length; j++) { char c = name[j]; if (j > num && char.IsUpper(c)) { stringBuilder.Append('_'); } stringBuilder.Append(char.ToUpper(c)); } stringBuilder.Append("_NAME"); _buffNameTokenLookup[i] = stringBuilder.ToString(); } stringBuilder = StringBuilderPool.ReturnStringBuilder(stringBuilder); } public static string GetBuffNameToken(BuffIndex buffIndex) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_0010: Expected I4, but got Unknown return ArrayUtils.GetSafe<string>(_buffNameTokenLookup, (int)buffIndex, ref string.Empty); } public static string GetBuffNameToken(BuffDef buffDef) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) return GetBuffNameToken((BuffIndex)((!Object.op_Implicit((Object)(object)buffDef)) ? (-1) : ((int)buffDef.buffIndex))); } public static string GetLocalizedBuffName(BuffDef buffDef) { if (!Object.op_Implicit((Object)(object)buffDef)) { return string.Empty; } if (buffDef.isElite) { string modifierToken = buffDef.eliteDef.modifierToken; if (!string.IsNullOrEmpty(modifierToken) && !Language.IsTokenInvalid(modifierToken)) { return Language.GetStringFormatted(modifierToken, new object[1] { string.Empty }).Trim(); } } string buffNameToken = GetBuffNameToken(buffDef); if (!string.IsNullOrEmpty(buffNameToken) && !Language.IsTokenInvalid(buffNameToken)) { return Language.GetString(buffNameToken); } return string.Empty; } [ConCommand(/*Could not decode attribute arguments.*/)] private static void CCPrintUnnamedBuffs(ConCommandArgs args) { //IL_000e: 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_0029: Unknown result type (might be due to invalid IL or missing references) bool argBool = ((ConCommandArgs)(ref args)).GetArgBool(0); for (int i = 0; i < BuffCatalog.buffCount; i++) { BuffIndex val = (BuffIndex)i; BuffDef buffDef = BuffCatalog.GetBuffDef(val); if (Object.op_Implicit((Object)(object)buffDef) && (!argBool || !buffDef.isHidden)) { string buffNameToken = GetBuffNameToken(val); if (string.IsNullOrEmpty(buffNameToken) || Language.IsTokenInvalid(buffNameToken)) { Debug.Log((object)(((Object)buffDef).name + ": " + buffNameToken)); } } } } } public static class CharacterBodyUtils { public static void MarkAllBodyStatsDirty() { foreach (CharacterBody readOnlyInstances in CharacterBody.readOnlyInstancesList) { readOnlyInstances.MarkAllStatsDirty(); } } } public static class CharacterMasterNotificationQueueUtils { [SystemInitializer(new Type[] { })] private static void Init() { InventoryExtensions.PickupTransformation.OnPickupTransformedServerGlobal += onPickupTransformedServerGlobal; } private static void onPickupTransformedServerGlobal(InventoryExtensions.PickupTransformation.TryTransformResult transformResult) { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 //IL_00b8: Unknown result type (might be due to invalid IL or missing references) //IL_00c3: Unknown result type (might be due to invalid IL or missing references) //IL_00c8: Unknown result type (might be due to invalid IL or missing references) //IL_005a: 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_006b: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Expected O, but got Unknown //IL_0077: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_009c: Unknown result type (might be due to invalid IL or missing references) //IL_00a3: Expected O, but got Unknown TransformationType transformationType = (TransformationType)transformResult.TransformationType; CharacterMaster val = default(CharacterMaster); if ((int)transformationType == -1 || !Object.op_Implicit((Object)(object)transformResult.Inventory) || !((Component)transformResult.Inventory).TryGetComponent<CharacterMaster>(ref val) || !Object.op_Implicit((Object)(object)val.playerCharacterMasterController)) { return; } if (Util.HasEffectiveAuthority(((Component)val).gameObject)) { CharacterMasterNotificationQueue notificationQueueForMaster = CharacterMasterNotificationQueue.GetNotificationQueueForMaster(val); if (Object.op_Implicit((Object)(object)notificationQueueForMaster)) { TransformationInfo val2 = new TransformationInfo(transformationType, (object)PickupCatalog.GetPickupDef(transformResult.TakenPickup.PickupIndex)); NotificationInfo val3 = new NotificationInfo((object)PickupCatalog.GetPickupDef(transformResult.GivenPickup.PickupIndex), val2, (CustomOverrideInfo)null, false, transformResult.GivenPickup.StackValues.temporaryStacksValue > 0f, 0); notificationQueueForMaster.PushNotification(val3, 6f); } } else { NetMessageExtensions.Send((INetMessage)(object)new PickupTransformationNotificationMessage(val, transformResult.TakenPickup.PickupIndex, transformResult.GivenPickup.PickupIndex, transformationType), ((NetworkBehaviour)val).connectionToClient); } } public static void SendPickupTransformNotification(CharacterMaster characterMaster, PickupIndex fromPickupIndex, PickupIndex toPickupIndex, TransformationType transformationType) { //IL_001f: Unknown result type (might be due to invalid IL or missing references) //IL_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Unknown result type (might be due to invalid IL or missing references) if (!NetworkServer.active) { Log.Error("Called on client", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfChaos\\Utilities\\CharacterMasterNotificationQueueUtils.cs", "SendPickupTransformNotification", 50); } else { NetMessageExtensions.Send((INetMessage)(object)new PickupTransformationNotificationMessage(characterMaster, fromPickupIndex, toPickupIndex, transformationType), (NetworkDestination)3); } } public static bool IsAnyNotificationQueued(CharacterMaster viewerMaster) { if (!Object.op_Implicit((Object)(object)viewerMaster) || !((NetworkBehaviour)viewerMaster).hasAuthority) { return false; } CharacterMasterNotificationQueue component = ((Component)viewerMaster).GetComponent<CharacterMasterNotificationQueue>(); if (Object.op_Implicit((Object)(object)component)) { return component.GetCurrentNotification() != (NotificationInfo)null; } return false; } } public static class ClampedConversion { [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Int32(uint value) { if (value > int.MaxValue) { return int.MaxValue; } return (int)value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int Int32(long value) { if (value > int.MaxValue) { return int.MaxValue; } if (value < int.MinValue) { return int.MinValue; } return (int)value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint UInt32(int value) { if ((long)value < 0L) { return 0u; } return (uint)value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint UInt32(long value) { if (value > uint.MaxValue) { return uint.MaxValue; } if (value < 0) { return 0u; } return (uint)value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static uint UInt32(ulong value) { if (value > uint.MaxValue) { return uint.MaxValue; } return (uint)value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static sbyte Int8(int value) { if (value > 127) { return sbyte.MaxValue; } if (value < -128) { return sbyte.MinValue; } return (sbyte)value; } [MethodImpl(MethodImplOptions.AggressiveInlining)] public static byte UInt8(int value) { if (value > 255) { return byte.MaxValue; } if (value < 0) { return 0; } return (byte)value; } } public static class ConVarFlagUtil { public const ConVarFlags SERVER = 2; } public static class CostUtils { public static bool AllowsZeroCost(CostTypeIndex costType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0009: Invalid comparison between Unknown and I4 if ((int)costType <= 3 || costType - 14 <= 1) { return true; } return false; } public static int GetMaxCost(CostTypeIndex costType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 if ((int)costType != 2) { if (costType - 7 <= 1) { return 1; } if ((int)costType != 15) { return int.MaxValue; } } return 99; } public static int GetMinCost(CostTypeIndex costType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0003: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Invalid comparison between Unknown and I4 if ((int)costType != 0) { if ((int)costType == 15) { return 10; } return 1; } return 0; } public static float ConvertCost(float cost, CostTypeIndex from, CostTypeIndex to) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_0008: Invalid comparison between Unknown and I4 //IL_000a: Unknown result type (might be due to invalid IL or missing references) //IL_000d: Invalid comparison between Unknown and I4 //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_0017: Invalid comparison between Unknown and I4 //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Invalid comparison between Unknown and I4 //IL_0026: Unknown result type (might be due to invalid IL or missing references) //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0034: Unknown result type (might be due to invalid IL or missing references) //IL_003b: 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_0088: Unknown result type (might be due to invalid IL or missing references) if (from == to) { return cost; } if ((int)to <= 0 || (int)to >= 16) { return 0f; } if ((int)from <= 0 || (int)from >= 16) { return GetMinCost(to); } int minCost = GetMinCost(from); int maxCost = GetMaxCost(from); int maxCost2 = GetMaxCost(to); int minCost2 = GetMinCost(to); if (maxCost < int.MaxValue && minCost != maxCost) { float num = Mathf.Clamp01(Mathf.InverseLerp((float)minCost, (float)maxCost, cost)); cost = (float)minCost - (50f - (float)minCost) * (1f + 1f / (num - 1f)); } cost *= getConversionRate(from) / getConversionRate(to); if (maxCost2 < int.MaxValue && minCost2 != maxCost2) { float num2 = 1f + 1f / (((float)minCost2 - cost) / (50f - (float)minCost2) - 1f); cost = Mathf.Lerp((float)minCost2, (float)maxCost2, num2); } cost = Mathf.Clamp(cost, (float)minCost2, (float)maxCost2); return cost; static float getConversionRate(CostTypeIndex costType) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Expected I4, but got Unknown switch (costType - 3) { case 1: return 25f; case 0: case 2: case 4: case 5: case 11: return 50f; case 9: return 75f; case 6: return 100f; case 3: case 7: case 8: case 10: return 150f; default: return 1f; } } } } public static class Ease { public static float InQuad(float t) { return t * t; } public static float OutQuad(float t) { return 1f - (1f - t) * (1f - t); } public static float InOutQuad(float t) { if (t < 0.5f) { return 2f * t * t; } float num = -2f * t + 2f; return 1f - num * num / 2f; } public static float InCubic(float t) { return t * t * t; } public static float OutCubic(float t) { float num = 1f - t; return 1f - num * num * num; } public static float InOutCubic(float t) { if (t < 0.5f) { return 4f * t * t * t; } float num = -2f * t + 2f; return 1f - num * num * num / 2f; } } public static class EffectCatalogUtils { private static readonly Dictionary<string, EffectIndex> _effectIndexByPrefabName = new Dictionary<string, EffectIndex>(); [SystemInitializer(new Type[] { typeof(EffectCatalog) })] private static void Init() { //IL_001b: 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_0088: Invalid comparison between Unknown and I4 //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) //IL_0081: Unknown result type (might be due to invalid IL or missing references) //IL_0078: Unknown result type (might be due to invalid IL or missing references) _effectIndexByPrefabName.Clear(); _effectIndexByPrefabName.EnsureCapacity(EffectCatalog.effectCount); for (EffectIndex val = (EffectIndex)0; (int)val < EffectCatalog.effectCount; val = (EffectIndex)(val + 1)) { EffectDef effectDef = EffectCatalog.GetEffectDef(val); if (effectDef != null && !string.IsNullOrWhiteSpace(effectDef.prefabName)) { if (_effectIndexByPrefabName.ContainsKey(effectDef.prefabName)) { Log.Warning("Duplicate effect prefab name '" + effectDef.prefabName + "'", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfChaos\\Utilities\\EffectCatalogUtils.cs", "Init", 23); } _effectIndexByPrefabName[effectDef.prefabName] = val; } } } public static EffectIndex FindEffectIndex(string effectPrefabName) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) return System.Collections.Generic.CollectionExtensions.GetValueOrDefault(_effectIndexByPrefabName, effectPrefabName, (EffectIndex)(-1)); } } public static class EliteUtils { private static EliteIndex[] _validEliteIndices = Array.Empty<EliteIndex>(); private static EquipmentIndex[] _validEliteEquipmentIndices = Array.Empty<EquipmentIndex>(); private static EquipmentIndex[] _allEliteEquipmentIndices = Array.Empty<EquipmentIndex>(); private static EliteIndex[] _runAvailableEliteIndices = Array.Empty<EliteIndex>(); public static bool HasAnyRunAvailableElites => _runAvailableEliteIndices.Length != 0; [SystemInitializer(new Type[] { typeof(EquipmentCatalog), typeof(EliteCatalog) })] private static void Init() { //IL_0030: 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_0037: 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_0069: Invalid comparison between Unknown and I4 //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0118: Unknown result type (might be due to invalid IL or missing references) //IL_0125: Unknown result type (might be due to invalid IL or missing references) int count = EliteCatalog.eliteList.Count; HashSet<EliteIndex> hashSet = new HashSet<EliteIndex>(count); HashSet<EquipmentIndex> hashSet2 = new HashSet<EquipmentIndex>(count); HashSet<EquipmentIndex> hashSet3 = new HashSet<EquipmentIndex>(count); foreach (EliteIndex elite in EliteCatalog.eliteList) { EliteDef eliteDef = EliteCatalog.GetEliteDef(elite); if (!Object.op_Implicit((Object)(object)eliteDef)) { continue; } EquipmentDef eliteEquipmentDef = eliteDef.eliteEquipmentDef; if (!Object.op_Implicit((Object)(object)eliteEquipmentDef) || (int)eliteEquipmentDef.equipmentIndex == -1) { continue; } hashSet3.Add(eliteEquipmentDef.equipmentIndex); if (!string.IsNullOrWhiteSpace(eliteDef.modifierToken) && !Language.IsTokenInvalid(eliteDef.modifierToken) && !((Object)eliteDef).name.EndsWith("Honor", StringComparison.OrdinalIgnoreCase)) { bool flag = ((eliteEquipmentDef.pickupModelReference == null || !((AssetReference)eliteEquipmentDef.pickupModelReference).RuntimeKeyIsValid()) ? (!Object.op_Implicit((Object)(object)eliteEquipmentDef.pickupModelPrefab) || ((Object)eliteEquipmentDef.pickupModelPrefab).name == "NullModel") : (((AssetReference)eliteEquipmentDef.pickupModelReference).RuntimeKey as string == "56b77f2cfa2f8d743ae18780a672ecb7")); if (!flag && hashSet2.Add(eliteEquipmentDef.equipmentIndex)) { hashSet.Add(elite); } } } _validEliteIndices = hashSet.ToArray(); Array.Sort(_validEliteIndices); _validEliteEquipmentIndices = hashSet2.ToArray(); Array.Sort(_validEliteEquipmentIndices); _allEliteEquipmentIndices = hashSet3.ToArray(); Array.Sort(_allEliteEquipmentIndices); if (_validEliteIndices.Length != 0) { Run.onRunStartGlobal += onRunStartGlobal; Run.onRunDestroyGlobal += onRunDestroyGlobal; } } private static void onRunStartGlobal(Run run) { //IL_001a: Unknown result type (might be due to invalid IL or missing references) //IL_001b: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Unknown result type (might be due to invalid IL or missing references) List<EliteIndex> list = new List<EliteIndex>(_validEliteIndices.Length); EliteIndex[] validEliteIndices = _validEliteIndices; foreach (EliteIndex val in validEliteIndices) { EliteDef eliteDef = EliteCatalog.GetEliteDef(val); if (Object.op_Implicit((Object)(object)eliteDef) && eliteDef.IsAvailable()) { list.Add(val); } } _runAvailableEliteIndices = list.ToArray(); } private static void onRunDestroyGlobal(Run run) { _runAvailableEliteIndices = Array.Empty<EliteIndex>(); } public static bool IsAvailable(EliteIndex eliteIndex) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return Array.BinarySearch(_validEliteIndices, eliteIndex) >= 0; } public static bool IsRunAvailable(EliteIndex eliteIndex) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return Array.BinarySearch(_runAvailableEliteIndices, eliteIndex) >= 0; } public static IReadOnlyList<EliteIndex> GetRunAvailableElites(bool ignoreEliteTierAvailability) { if (!ignoreEliteTierAvailability) { return GetAllCombatDirectorElites(); } return Array.AsReadOnly(_runAvailableEliteIndices); } public static IReadOnlyList<EliteIndex> GetAllCombatDirectorElites() { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) //IL_0061: Unknown result type (might be due to invalid IL or missing references) List<EliteIndex> list = new List<EliteIndex>(_runAvailableEliteIndices.Length); EliteTierDef[] eliteTiers = CombatDirector.eliteTiers; foreach (EliteTierDef val in eliteTiers) { if (!val.CanSelect((EliteRules)0)) { continue; } EliteDef[] eliteTypes = val.eliteTypes; foreach (EliteDef val2 in eliteTypes) { if (Object.op_Implicit((Object)(object)val2) && IsRunAvailable(val2.eliteIndex) && !list.Contains(val2.eliteIndex)) { list.Add(val2.eliteIndex); } } } return list.AsReadOnly(); } public static bool IsEliteEquipment(EquipmentIndex equipmentIndex) { //IL_0005: Unknown result type (might be due to invalid IL or missing references) return Array.BinarySearch(_allEliteEquipmentIndices, equipmentIndex) >= 0; } } public record struct EquipmentLocation(uint Slot, uint Set); public sealed class EventWaiter { private record struct EventInfo(bool HasInvoked); private bool _allEventsInvoked; public bool ResetAfterAllEventsInvoked; private readonly List<EventInfo> _events = new List<EventInfo>(); public event Action OnAnyEventInvoked; public event Action OnAllEventsInvoked; public Action GetListener() { _events.Add(new EventInfo(HasInvoked: false)); int eventIndex = _events.Count - 1; return delegate { if (eventIndex >= 0 && eventIndex < _events.Count && !_events[eventIndex].HasInvoked) { setHasEventInvoked(eventIndex, isInvoked: true); onEventInvoked(); } }; } private void setHasEventInvoked(int index, bool isInvoked) { if (index >= 0 && index < _events.Count) { EventInfo value = _events[index]with { HasInvoked = isInvoked }; _events[index] = value; } } private void onEventInvoked() { this.OnAnyEventInvoked?.Invoke(); if (_allEventsInvoked || !_events.All((EventInfo e) => e.HasInvoked)) { return; } this.OnAllEventsInvoked?.Invoke(); if (ResetAfterAllEventsInvoked) { for (int i = 0; i < _events.Count; i++) { setHasEventInvoked(i, isInvoked: false); } } else { _allEventsInvoked = true; } } } public static class ExpansionUtils { public static ResourceAvailability Availability = default(ResourceAvailability); public static ExpansionIndex DLC1 { get; private set; } = (ExpansionIndex)(-1); public static ExpansionIndex DLC2 { get; private set; } = (ExpansionIndex)(-1); public static ExpansionIndex DLC3 { get; private set; } = (ExpansionIndex)(-1); public static bool DLC1Enabled { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return IsExpansionEnabled(DLC1); } } public static bool DLC2Enabled { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return IsExpansionEnabled(DLC2); } } public static bool DLC3Enabled { [MethodImpl(MethodImplOptions.AggressiveInlining)] get { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return IsExpansionEnabled(DLC3); } } [SystemInitializer(new Type[] { typeof(ExpansionCatalog) })] private unsafe static void Init() { //IL_006e: Unknown result type (might be due to invalid IL or missing references) //IL_0073: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing references) //IL_0009: 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_0052: Unknown result type (might be due to invalid IL or missing references) //IL_005f: Unknown result type (might be due to invalid IL or missing references) for (int i = 0; i < ExpansionCatalog.expansionDefs.Length; i++) { ExpansionDef val = (ExpansionDef)Unsafe.Read<object>((void*)ExpansionCatalog.expansionDefs[i]); switch (((Object)val).name) { case "DLC1": DLC1 = val.expansionIndex; break; case "DLC2": DLC2 = val.expansionIndex; break; case "DLC3": DLC3 = val.expansionIndex; break; } } ((ResourceAvailability)(ref Availability)).MakeAvailable(); } public unsafe static ExpansionDef GetExpansionDef(ExpansionIndex index) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Unknown result type (might be due to invalid IL or missing references) //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_0014: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0022: Expected I4, but got Unknown if ((long)(ulong)index >= (long)ExpansionCatalog.expansionDefs.Length) { return null; } return (ExpansionDef)Unsafe.Read<object>((void*)ExpansionCatalog.expansionDefs[(int)index]); } public static bool IsExpansionEnabled(ExpansionIndex expansionIndex) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return IsExpansionEnabled(GetExpansionDef(expansionIndex)); } public static bool IsExpansionEnabled(ExpansionDef expansionDef) { if (Object.op_Implicit((Object)(object)expansionDef)) { if (Object.op_Implicit((Object)(object)Run.instance)) { return Run.instance.IsExpansionEnabled(expansionDef); } return false; } return true; } public static bool AllExpansionsEnabled(IEnumerable<ExpansionIndex> expansions) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) foreach (ExpansionIndex expansion in expansions) { if (!IsExpansionEnabled(expansion)) { return false; } } return true; } public static bool AllExpansionsEnabled(IEnumerable<ExpansionDef> expansions) { foreach (ExpansionDef expansion in expansions) { if (!IsExpansionEnabled(expansion)) { return false; } } return true; } private static void addAllRequiredExpansions(GameObject obj, List<ExpansionDef> dest) { if (!Object.op_Implicit((Object)(object)obj)) { return; } ExpansionRequirementComponent[] components = obj.GetComponents<ExpansionRequirementComponent>(); ListExtensions.EnsureCapacity(dest, dest.Count + components.Length); ExpansionRequirementComponent[] array = components; foreach (ExpansionRequirementComponent val in array) { if (Object.op_Implicit((Object)(object)val.requiredExpansion)) { dest.Add(val.requiredExpansion); } } CharacterMaster val2 = default(CharacterMaster); if (obj.TryGetComponent<CharacterMaster>(ref val2) && Object.op_Implicit((Object)(object)val2.bodyPrefab)) { addAllRequiredExpansions(val2.bodyPrefab, dest); } } public static IReadOnlyList<ExpansionDef> GetObjectRequiredExpansions(GameObject obj) { if (!Object.op_Implicit((Object)(object)obj)) { return Array.Empty<ExpansionDef>(); } List<ExpansionDef> list = new List<ExpansionDef>(); addAllRequiredExpansions(obj, list); list.TrimExcess(); return list.AsReadOnly(); } public static IReadOnlyList<ExpansionIndex> GetObjectRequiredExpansionIndices(GameObject obj) { //IL_0043: Unknown result type (might be due to invalid IL or missing references) //IL_0049: Expected I4, but got Unknown if (!Object.op_Implicit((Object)(object)obj)) { return Array.Empty<ExpansionIndex>(); } List<ExpansionDef> list = new List<ExpansionDef>(); addAllRequiredExpansions(obj, list); if (list.Count <= 0) { return Array.Empty<ExpansionIndex>(); } ExpansionIndex[] array = (ExpansionIndex[])(object)new ExpansionIndex[list.Count]; for (int i = 0; i < array.Length; i++) { array[i] = (ExpansionIndex)(int)list[i].expansionIndex; } return array; } public static bool IsObjectExpansionAvailable(GameObject obj) { return AllExpansionsEnabled(GetObjectRequiredExpansions(obj)); } } public static class FormatUtils { public static string GetBestBodyName(CharacterBody body) { if (!Object.op_Implicit((Object)(object)body)) { return "null"; } string bestBodyName = Util.GetBestBodyName(((Component)body).gameObject); if (!string.IsNullOrWhiteSpace(bestBodyName)) { return bestBodyName; } return ((object)body).ToString(); } public static string GetBestItemDisplayName(ItemIndex item) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_000a: Unknown result type (might be due to invalid IL or missing references) if ((int)item == -1) { return "None"; } return GetBestItemDisplayName(ItemCatalog.GetItemDef(item)); } public static string GetBestItemDisplayName(ItemDef item) { if (!Object.op_Implicit((Object)(object)item)) { return "null"; } if (!string.IsNullOrWhiteSpace(item.nameToken) && !Language.IsTokenInvalid(item.nameToken)) { string @string = Language.GetString(item.nameToken); if (!string.IsNullOrWhiteSpace(@string)) { return @string; } } return ((Object)item).name; } public static string GetBestEquipmentDisplayName(EquipmentIndex equipmentIndex) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0002: Invalid comparison between Unknown and I4 //IL_000a: Unknown result type (might be due to invalid IL or missing references) if ((int)equipmentIndex == -1) { return "None"; } return GetBestEquipmentDisplayName(EquipmentCatalog.GetEquipmentDef(equipmentIndex)); } public static string GetBestEquipmentDisplayName(EquipmentDef equipmentDef) { if (!Object.op_Implicit((Object)(object)equipmentDef)) { return "null"; } if (!string.IsNullOrEmpty(equipmentDef.nameToken) && !Language.IsTokenInvalid(equipmentDef.nameToken)) { string @string = Language.GetString(equipmentDef.nameToken); if (!string.IsNullOrWhiteSpace(@string)) { return @string; } } return ((Object)equipmentDef).name; } public static string GetBestDifficultyDisplayName(DifficultyIndex difficultyIndex) { //IL_0000: Unknown result type (might be due to invalid IL or missing references) return GetBestDifficultyDisplayName(DifficultyCatalog.GetDifficultyDef(difficultyIndex)); } public static string GetBestDifficultyDisplayName(DifficultyDef difficultyDef) { if (difficultyDef == null) { return "null"; } return Language.GetString(difficultyDef.nameToken); } public static string FormatTimeSeconds(float seconds) { if (seconds < 120.5f) { return seconds.ToString((seconds >= 9.95f) ? "F0" : "F1") + "s"; } int num = Mathf.FloorToInt(seconds / 60f); int num2 = Mathf.RoundToInt(seconds % 60f); return $"{num}:{num2:D2}"; } } public interface IAsyncOperationCoroutine : IEnumerator { float Progress { get; } } public static class InputUtils { private static MemoizedGetComponent<TMP_InputField> _currentSelectedObjectTMPInputField; private static MemoizedGetComponent<InputField> _currentSelectedObjectInputField; public static bool IsUsingInputField() { EventSystem val = (EventSystem)(object)MPEventSystemManager.FindEventSystem(ReInput.players.GetPlayer(0)); if (Object.op_Implicit((Object)(object)val)) { GameObject currentSelectedGameObject = val.currentSelectedGameObject; if (Object.op_Implicit((Object)(object)_currentSelectedObjectTMPInputField.Get(currentSelectedGameObject)) || Object.op_Implicit((Object)(object)_currentSelectedObjectInputField.Get(currentSelectedGameObject))) { return true; } } return false; } } public static class InstanceUtils { public static void DestroyAllTrackedInstances<T>(bool destroyGameObject = false) where T : MonoBehaviour { List<T> instancesList = InstanceTracker.GetInstancesList<T>(); for (int num = instancesList.Count - 1; num >= 0; num--) { T val = instancesList[num]; if (Object.op_Implicit((Object)(object)val)) { Object.Destroy((Object)(destroyGameObject ? ((Component)(object)val).gameObject : ((object)val))); } } } } public sealed class ItemTierPickupRulesOverride : IDisposable { private static PickupRules[] _originalPickupRules = Array.Empty<PickupRules>(); private static readonly List<ItemTierPickupRulesOverride> _activeRuleOverrides = new List<ItemTierPickupRulesOverride>(); private PickupRules _overrideRules; public PickupRules OverrideRules { get { //IL_0001: Unknown result type (might be due to invalid IL or missing references) return _overrideRules; } set { //IL_0001: Unknown result type (might be due to invalid IL or missing references) //IL_0006: Unknown result type (might be due to invalid IL or missing references) //IL_000b: Unknown result type (might be due to invalid IL or missing references) //IL_000c: Unknown result type (might be due to invalid IL or missing references) if (_overrideRules != value) { _overrideRules = value; refreshPickupRules(); } } } [SystemInitializer(new Type[] { typeof(ItemTierCatalog) })] private unsafe static void Init() { //IL_0000: Unknown result type (might be due to invalid IL or missing references) //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_002a: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Expected I4, but got Unknown ReadOnlyArray<ItemTierDef> allItemTierDefs = ItemTierCatalog.allItemTierDefs; _originalPickupRules = (PickupRules[])(object)new PickupRules[allItemTierDefs.Length]; for (int i = 0; i < allItemTierDefs.Length; i++) { _originalPickupRules[i] = (PickupRules)(int)((ItemTierDef)Unsafe.Read<object>((void*)allItemTierDefs[i])).pickupRules; } } private static void refreshPickupRules() { //IL_001f: Unknown result type (might be due to invalid IL or missing references) if (_activeRuleOverrides.Count > 0) { List<ItemTierPickupRulesOverride> activeRuleOverrides = _activeRuleOverrides; setOverridePickupRules(activeRuleOverrides[activeRuleOverrides.Count - 1].OverrideRules); } else { restorePickupRules(); } } private unsafe static void setOverridePickupRules(PickupRules overridePickupRules) { //IL_001e: Unknown result type (might be due to invalid IL or missing references) //IL_0023: Unknown result type (might be due to invalid IL or missing references) //IL_0004: Unknown result type (might be due to invalid IL or missing r
plugins/RiskOfChaos/RiskOfChaos_PatcherInterop.dll
Decompiled 6 months agousing System; using System.Diagnostics; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using Microsoft.CodeAnalysis; using RoR2.Projectile; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: InternalsVisibleTo("RiskOfChaos")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("RiskOfChaos_PatcherInterop")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+185a0f39c4b3d300dea0a9a7bc277dc0938d8ec6")] [assembly: AssemblyProduct("RiskOfChaos_PatcherInterop")] [assembly: AssemblyTitle("RiskOfChaos_PatcherInterop")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace RiskOfChaos.PatcherInterop { internal static class InteropUtils { public static float? DecodePackedOverrideValue(float overridePlusOne) { float num = overridePlusOne - 1f; if (num < 0f) { return null; } return num; } public static float EncodePackedOverrideValue(float? overrideValue) { if (!overrideValue.HasValue) { return 0f; } return overrideValue.Value + 1f; } } internal static class ProjectileInteropExtensions { public static float GetProcCoefficientOverridePlusOne(this in FireProjectileInfo fireProjectileInfo) { return fireProjectileInfo.roc_procCoefficientOverridePlusOne; } public static float? GetProcCoefficientOverride(this in FireProjectileInfo fireProjectileInfo) { return InteropUtils.DecodePackedOverrideValue(fireProjectileInfo.roc_procCoefficientOverridePlusOne); } public static void SetProcCoefficientOverridePlusOne(this ref FireProjectileInfo fireProjectileInfo, float value) { fireProjectileInfo.roc_procCoefficientOverridePlusOne = value; } public static void SetProcCoefficientOverride(this ref FireProjectileInfo fireProjectileInfo, float? value) { fireProjectileInfo.roc_procCoefficientOverridePlusOne = InteropUtils.EncodePackedOverrideValue(value); } } }
plugins/RiskOfChaos/RiskOfTwitch.dll
Decompiled 6 months agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Net.WebSockets; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Authentication; using System.Security.Cryptography; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Web; using Microsoft.CodeAnalysis; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using RiskOfTwitch.Chat.Message; using RiskOfTwitch.Chat.Notification; using RiskOfTwitch.Logging; using RiskOfTwitch.User; using RiskOfTwitch.WebSockets; using UnityEngine; [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("RiskOfTwitch")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+185a0f39c4b3d300dea0a9a7bc277dc0938d8ec6")] [assembly: AssemblyProduct("RiskOfTwitch")] [assembly: AssemblyTitle("RiskOfTwitch")] [assembly: AssemblyVersion("1.0.0.0")] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace RiskOfTwitch { public static class Authentication { public const string CLIENT_ID = "2h96zmad9nhz11unv407c9ou6i6ofj"; public const string AUTH_REDIRECT_URL = "http://localhost:4000/roc/oauth/redirect"; private static readonly byte[] _authRedirectResponseBytes = Encoding.ASCII.GetBytes("<!DOCTYPE html>\r\n<html lang=\"en\">\r\n<head>\r\n <meta charset=\"UTF-8\">\r\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\r\n</head>\r\n<body>\r\nAuthentication complete. You may close this window.\r\n <script>\r\n var url = window.location;\r\n url.replace(window.location.hash, \"\");\r\n fetch(url, {\r\n method: 'GET',\r\n headers: {\r\n 'fragment': window.location.hash\r\n }\r\n });\r\n </script>\r\n</body>"); public static string CreateAuthorizeUrl(string scopes, out string authState) { using (RandomNumberGenerator randomNumberGenerator = RandomNumberGenerator.Create()) { byte[] array = new byte[16]; randomNumberGenerator.GetBytes(array); StringBuilder stringBuilder = new StringBuilder(32); for (int i = 0; i < 16; i++) { stringBuilder.Append(array[i].ToString("x2")); } authState = stringBuilder.ToString(); } return "https://id.twitch.tv/oauth2/authorize?response_type=token&client_id=2h96zmad9nhz11unv407c9ou6i6ofj&redirect_uri=http://localhost:4000/roc/oauth/redirect&scope=" + HttpUtility.UrlEncode(scopes) + "&state=" + authState; } public static async Task<Result<string>> AuthenticateUserAccessToken(string scopes, CancellationToken cancellationToken = default(CancellationToken)) { Application.OpenURL(CreateAuthorizeUrl(scopes, out var authState)); using HttpListener httpListener = new HttpListener(); httpListener.Prefixes.Add("http://localhost:4000/roc/oauth/redirect/"); httpListener.Start(); HttpListenerContext context2 = await httpListener.GetContextAsync().ConfigureAwait(continueOnCapturedContext: false); context2.Response.ContentType = "text/html"; context2.Response.ContentEncoding = Encoding.ASCII; context2.Response.ContentLength64 = _authRedirectResponseBytes.LongLength; await context2.Response.OutputStream.WriteAsync(_authRedirectResponseBytes, 0, _authRedirectResponseBytes.Length, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); context2.Response.Close(); context2 = await httpListener.GetContextAsync().ConfigureAwait(continueOnCapturedContext: false); string text = context2.Request.Headers["fragment"]; Uri url = context2.Request.Url; Dictionary<string, string> destination = new Dictionary<string, string>(); if (url != null) { string text2 = url.Query; if (!string.IsNullOrEmpty(text2)) { if (text2[0] == '?') { text2 = text2.Substring(1); } UrlUtils.SplitUrlQueries(text2, destination); } } Dictionary<string, string> dictionary = new Dictionary<string, string>(); if (!string.IsNullOrEmpty(text)) { if (text[0] == '#') { text = text.Substring(1); } UrlUtils.SplitUrlQueries(text, dictionary); } context2.Response.StatusCode = 200; context2.Response.KeepAlive = false; context2.Response.Close(); if (!dictionary.TryGetValue("state", out var value) || !string.Equals(authState, value)) { return new Result<string>(new AuthenticationException("Invalid authentication state")); } if (!dictionary.TryGetValue("access_token", out var value2)) { return new Result<string>(new AuthenticationException("No token received")); } return value2; } public static async Task<Result<AuthenticationTokenValidationResponse>> GetAccessTokenValidationAsync(string accessToken, CancellationToken cancellationToken = default(CancellationToken)) { using HttpClient client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken); using HttpResponseMessage validationResponse = await client.GetAsync("https://id.twitch.tv/oauth2/validate", cancellationToken).ConfigureAwait(continueOnCapturedContext: false); string text = await validationResponse.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false); if (!validationResponse.IsSuccessStatusCode) { if (validationResponse.StatusCode == HttpStatusCode.Unauthorized && !string.IsNullOrEmpty(text) && text.Contains("invalid access token", StringComparison.OrdinalIgnoreCase)) { return new Result<AuthenticationTokenValidationResponse>(new InvalidAccessTokenException()); } return new Result<AuthenticationTokenValidationResponse>(new HttpResponseException(validationResponse)); } try { return JsonConvert.DeserializeObject<AuthenticationTokenValidationResponse>(text); } catch (Exception exception) { return new Result<AuthenticationTokenValidationResponse>(exception); } } } [Serializable] public sealed class AuthenticationTokenValidationResponse { [JsonProperty("client_id")] public string ClientId { get; set; } = string.Empty; [JsonProperty("login")] public string Username { get; set; } = string.Empty; [JsonProperty("scopes")] public string[] Scopes { get; set; } = Array.Empty<string>(); [JsonProperty("user_id")] public string UserID { get; set; } = string.Empty; [JsonProperty("expires_in")] private int expiresInSeconds { get { return (int)Math.Round(ExpiryDate.TimeUntil.TotalSeconds); } set { ExpiryDate = DateTime.Now.AddSeconds(value); } } [JsonIgnore] public DateTimeStamp ExpiryDate { get; set; } } public readonly struct DateTimeStamp : IEquatable<DateTimeStamp> { public readonly DateTime Time; public static DateTimeStamp Now => new DateTimeStamp(DateTime.Now); public TimeSpan TimeSince => DateTime.Now - Time; public TimeSpan TimeUntil => Time - DateTime.Now; public bool IsFuture => TimeUntil.Ticks > 0; public bool HasPassed => TimeSince.Ticks > 0; public DateTimeStamp(DateTime time) { Time = time; } public override string ToString() { StringBuilder stringBuilder = new StringBuilder(); stringBuilder.Append(Time.ToString()); if (IsFuture) { stringBuilder.Append($" (in {TimeUntil})"); } else { stringBuilder.Append($" ({TimeSince} ago)"); } return stringBuilder.ToString(); } public override bool Equals(object obj) { if (obj is DateTimeStamp other) { return Equals(other); } return false; } public bool Equals(DateTimeStamp other) { return Time == other.Time; } public override int GetHashCode() { return 615635108 + Time.GetHashCode(); } public static implicit operator DateTimeStamp(DateTime time) { return new DateTimeStamp(time); } public static bool operator ==(DateTimeStamp left, DateTimeStamp right) { return left.Equals(right); } public static bool operator !=(DateTimeStamp left, DateTimeStamp right) { return !(left == right); } public static bool operator <(DateTimeStamp left, DateTimeStamp right) { return left.Time < right.Time; } public static bool operator <(DateTimeStamp left, DateTime right) { return left.Time < right; } public static bool operator <(DateTime left, DateTimeStamp right) { return left < right.Time; } public static bool operator >(DateTimeStamp left, DateTimeStamp right) { return left.Time > right.Time; } public static bool operator >(DateTimeStamp left, DateTime right) { return left.Time > right; } public static bool operator >(DateTime left, DateTimeStamp right) { return left > right.Time; } public static bool operator <=(DateTimeStamp left, DateTimeStamp right) { return left.Time <= right.Time; } public static bool operator <=(DateTimeStamp left, DateTime right) { return left.Time <= right; } public static bool operator <=(DateTime left, DateTimeStamp right) { return left <= right.Time; } public static bool operator >=(DateTimeStamp left, DateTimeStamp right) { return left.Time >= right.Time; } public static bool operator >=(DateTimeStamp left, DateTime right) { return left.Time >= right; } public static bool operator >=(DateTime left, DateTimeStamp right) { return left >= right.Time; } } public sealed class HttpResponseException : Exception { public HttpStatusCode StatusCode { get; } public string ReasonPhrase { get; } public HttpResponseException(HttpStatusCode statusCode, string reasonPhrase) : base($"{statusCode} ({reasonPhrase})") { StatusCode = statusCode; ReasonPhrase = reasonPhrase; } public HttpResponseException(HttpResponseMessage responseMessage) : this(responseMessage.StatusCode, responseMessage.ReasonPhrase) { } } public sealed class InvalidAccessTokenException : Exception { public InvalidAccessTokenException() : base("The provided access token is not valid or has expired") { } } public static class Log { private static readonly object _stringBuilderLock; private static readonly StringBuilder _sharedStringBuilder; private static readonly int _cachedCallerPathPrefixLength; public static ILogSource LogSource { get; set; } static Log() { LogSource = new ConsoleLogSource(); _stringBuilderLock = new object(); _sharedStringBuilder = new StringBuilder(256); _cachedCallerPathPrefixLength = getCallerPathPrefixLength("D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\Log.cs"); static int getCallerPathPrefixLength([CallerFilePath] string callerPath = null) { int num = callerPath.LastIndexOf("RiskOfTwitch"); if (num >= 0) { return num; } Error_NoCallerPrefix("[RiskOfTwitch] Logger failed to determine caller path prefix length"); return 0; } } private static StringBuilder AppendCallerPrefix(this StringBuilder stringBuilder, string callerPath, string callerMemberName, int callerLineNumber) { return stringBuilder.Append(callerPath, _cachedCallerPathPrefixLength, callerPath.Length - _cachedCallerPathPrefixLength).Append(':').Append(callerLineNumber) .Append(" (") .Append(callerMemberName) .Append("):"); } private static StringBuilder buildCallerLogString(string callerPath, string callerMemberName, int callerLineNumber, object data) { lock (_stringBuilderLock) { return _sharedStringBuilder.Clear().AppendCallerPrefix(callerPath, callerMemberName, callerLineNumber).Append(' ') .Append(data); } } [Conditional("DEBUG")] internal static void Debug(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { LogSource.Log(buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data), LogType.Debug); } [MethodImpl(MethodImplOptions.AggressiveInlining)] [Conditional("DEBUG")] internal static void Debug_NoCallerPrefix(object data) { LogSource.Log(data, LogType.Debug); } internal static void Error(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { LogSource.Log(buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data), LogType.Error); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Error_NoCallerPrefix(object data) { LogSource.Log(data, LogType.Error); } internal static void Fatal(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { LogSource.Log(buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data), LogType.Fatal); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Fatal_NoCallerPrefix(object data) { LogSource.Log(data, LogType.Fatal); } internal static void Info(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { LogSource.Log(buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data), LogType.Info); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Info_NoCallerPrefix(object data) { LogSource.Log(data, LogType.Info); } internal static void Message(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { LogSource.Log(buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data), LogType.Message); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Message_NoCallerPrefix(object data) { LogSource.Log(data, LogType.Message); } internal static void Warning(object data, [CallerFilePath] string callerPath = "", [CallerMemberName] string callerMemberName = "", [CallerLineNumber] int callerLineNumber = -1) { LogSource.Log(buildCallerLogString(callerPath, callerMemberName, callerLineNumber, data), LogType.Warning); } [MethodImpl(MethodImplOptions.AggressiveInlining)] internal static void Warning_NoCallerPrefix(object data) { LogSource.Log(data, LogType.Warning); } } public sealed class Result<T> { private readonly T _value; public bool IsSuccess { get; } public Exception Exception { get; } public T Value { get { if (!IsSuccess) { throw new ArgumentException("Result is not success, cannot get value"); } return _value; } } private Result(T value, Exception exception, bool isSuccess) { _value = value; Exception = exception; IsSuccess = isSuccess; } public Result(T value) : this(value, (Exception)null, isSuccess: true) { } public Result(Exception exception) : this(default(T), exception, isSuccess: false) { } public static implicit operator Result<T>(T value) { return new Result<T>(value); } } public static class StaticTwitchAPI { public static async Task<Result<GetUsersResponse>> GetUsers(string accessToken, string[] userIds, string[] usernames, CancellationToken cancellationToken = default(CancellationToken)) { if (userIds == null) { userIds = Array.Empty<string>(); } if (usernames == null) { usernames = Array.Empty<string>(); } int num = userIds.Length + usernames.Length; if (num == 0) { return GetUsersResponse.Empty; } if (num > 100) { return new Result<GetUsersResponse>(new ArgumentOutOfRangeException("userIds, usernames", "Combined size of user ids and usernames cannot exceed 100")); } using HttpClient client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken); client.DefaultRequestHeaders.Add("Client-Id", "2h96zmad9nhz11unv407c9ou6i6ofj"); StringBuilder stringBuilder = new StringBuilder(num * 25); string[] array = userIds; foreach (string arg in array) { if (stringBuilder.Length > 0) { stringBuilder.Append('&'); } stringBuilder.AppendFormat("id={0}", arg); } array = usernames; foreach (string arg2 in array) { if (stringBuilder.Length > 0) { stringBuilder.Append('&'); } stringBuilder.AppendFormat("login={0}", arg2); } using HttpResponseMessage getUsersResponseMessage = await client.GetAsync($"https://api.twitch.tv/helix/users?{stringBuilder}", cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (!getUsersResponseMessage.IsSuccessStatusCode) { return new Result<GetUsersResponse>(new HttpResponseException(getUsersResponseMessage)); } GetUsersResponse getUsersResponse; try { getUsersResponse = JsonConvert.DeserializeObject<GetUsersResponse>(await getUsersResponseMessage.Content.ReadAsStringAsync().ConfigureAwait(continueOnCapturedContext: false)); } catch (JsonException val) { return new Result<GetUsersResponse>((Exception)val); } return getUsersResponse; } } public static class UrlUtils { public static void SplitUrlQueries(string queries, IDictionary<string, string> destination) { if (destination == null) { throw new ArgumentNullException("destination"); } if (string.IsNullOrWhiteSpace(queries)) { return; } string[] array = queries.Split(new char[1] { '&' }, StringSplitOptions.RemoveEmptyEntries); for (int i = 0; i < array.Length; i++) { string[] array2 = array[i].Split('='); if (array2.Length == 2) { string text = HttpUtility.UrlDecode(array2[0]).Trim(); string value = HttpUtility.UrlDecode(array2[1]).Trim(); if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(value) && !destination.ContainsKey(text)) { destination.Add(text, value); } } } } } } namespace RiskOfTwitch.WebSockets { internal abstract class ClientWebSocketConnection : IDisposable { private ClientWebSocket _client; private readonly CancellationTokenSource _objectDisposedTokenSource = new CancellationTokenSource(); private bool _isReconnecting; private bool _hasEverConnected; private bool _isDisposed; public Uri ConnectionUrl { get; set; } public bool AutoReconnect { get; set; } = true; public TimeSpan ConnectionTimeout { get; set; } = TimeSpan.FromSeconds(30.0); public WebSocketState? State => _client?.State; public ClientWebSocketConnection(Uri url) { ConnectionUrl = url; } public void Dispose() { if (_isDisposed) { return; } _isDisposed = true; _objectDisposedTokenSource.Cancel(); _objectDisposedTokenSource.Dispose(); if (_client != null) { try { Disconnect().Wait(TimeSpan.FromSeconds(2.0)); } catch (Exception data) { Log.Error(data, "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\WebSockets\\ClientWebSocketConnection.cs", "Dispose", 51); } _client?.Dispose(); _client = null; } } private void throwIfDisposed() { lock (this) { if (_isDisposed) { throw new ObjectDisposedException(string.Format("{0} ({1})", "ClientWebSocketConnection", ConnectionUrl)); } } } protected virtual ClientWebSocket createClient() { ClientWebSocket clientWebSocket = new ClientWebSocket(); clientWebSocket.Options.KeepAliveInterval = ConnectionTimeout; return clientWebSocket; } public async Task Connect(CancellationToken cancellationToken = default(CancellationToken)) { throwIfDisposed(); if (_client != null) { if (State.GetValueOrDefault() == WebSocketState.Connecting || State.GetValueOrDefault() == WebSocketState.Open) { Log.Error("Already connected", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\WebSockets\\ClientWebSocketConnection.cs", "Connect", 87); return; } Log.Warning("Connecting while there is still an existing client instance, disposing old instance", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\WebSockets\\ClientWebSocketConnection.cs", "Connect", 91); _client.Dispose(); } CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_objectDisposedTokenSource.Token, cancellationToken); _client = createClient(); await _client.ConnectAsync(ConnectionUrl, cancellationTokenSource.Token).ConfigureAwait(continueOnCapturedContext: false); if (!_hasEverConnected) { Task.Run(() => updateLoop(_objectDisposedTokenSource.Token)); _hasEverConnected = true; } } public virtual async Task Disconnect(CancellationToken cancellationToken = default(CancellationToken)) { if (_client != null) { if (State >= WebSocketState.CloseSent) { _client.Dispose(); _client = null; return; } CancellationTokenSource cancellationTokenSource = CancellationTokenSource.CreateLinkedTokenSource(_objectDisposedTokenSource.Token, cancellationToken); await _client.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "", cancellationTokenSource.Token).ConfigureAwait(continueOnCapturedContext: false); _client?.Dispose(); _client = null; } } public async Task Reconnect(TimeSpan delay = default(TimeSpan), CancellationToken cancellationToken = default(CancellationToken)) { _isReconnecting = true; try { await Disconnect(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); await Task.Delay(delay).ConfigureAwait(continueOnCapturedContext: false); await Connect(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } finally { _isReconnecting = false; } } private async Task updateLoop(CancellationToken cancellationToken) { while (!cancellationToken.IsCancellationRequested) { if (_client == null) { if (AutoReconnect && !_isReconnecting) { await Connect(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } } else if (State.GetValueOrDefault() == WebSocketState.Open || State.GetValueOrDefault() == WebSocketState.CloseSent) { try { await handleNextMessageAsync(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } catch (Exception ex) when (!(ex is OperationCanceledException)) { Log.Error_NoCallerPrefix($"Unhandled exception handling web socket message: {ex}"); await Reconnect(TimeSpan.FromSeconds(1.0), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } } } } private async Task<WebSocketMessage> receiveMessageAsync(CancellationToken cancellationToken) { byte[] receivedData = new byte[1024]; int totalReceivedDataLength = 0; WebSocketReceiveResult webSocketReceiveResult; while (true) { if (totalReceivedDataLength >= receivedData.Length) { Array.Resize(ref receivedData, receivedData.Length + 1024); continue; } ArraySegment<byte> buffer = new ArraySegment<byte>(receivedData, totalReceivedDataLength, receivedData.Length - totalReceivedDataLength); webSocketReceiveResult = await _client.ReceiveAsync(buffer, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); totalReceivedDataLength += webSocketReceiveResult.Count; if (webSocketReceiveResult.EndOfMessage) { break; } } return new WebSocketMessage(new ArraySegment<byte>(receivedData, 0, totalReceivedDataLength), webSocketReceiveResult); } private async Task handleNextMessageAsync(CancellationToken cancellationToken) { using CancellationTokenSource timeoutTokenSource = new CancellationTokenSource(ConnectionTimeout); using CancellationTokenSource cancelledOrTimedOutTokenSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, timeoutTokenSource.Token); WebSocketMessage message; try { message = await receiveMessageAsync(cancelledOrTimedOutTokenSource.Token).ConfigureAwait(continueOnCapturedContext: false); } catch (OperationCanceledException) { if (timeoutTokenSource.Token.IsCancellationRequested) { Log.Info("WebSocket connection timed out, attempting reconnect...", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\WebSockets\\ClientWebSocketConnection.cs", "handleNextMessageAsync", 212); await Reconnect(TimeSpan.FromSeconds(1.0), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); return; } throw; } if (message.MessageType == WebSocketMessageType.Close) { if (message.CloseStatus.GetValueOrDefault() != WebSocketCloseStatus.NormalClosure) { if (shouldReconnect(message)) { Log.Info($"WebSocket connection closed (status={message.CloseStatus}, description='{message.CloseStatusDescription}'), attempting reconnect...", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\WebSockets\\ClientWebSocketConnection.cs", "handleNextMessageAsync", 227); await Reconnect(TimeSpan.FromSeconds(1.0), cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } else { Log.Info($"WebSocket connection closed (status={message.CloseStatus}, description='{message.CloseStatusDescription}'), not attempting reconnect", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\WebSockets\\ClientWebSocketConnection.cs", "handleNextMessageAsync", 233); AutoReconnect = false; await Disconnect(cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } } else { Log.Info("WebSocket connection closed", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\WebSockets\\ClientWebSocketConnection.cs", "handleNextMessageAsync", 241); } } else { await handleSocketMessageAsync(message, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } } protected abstract Task handleSocketMessageAsync(WebSocketMessage message, CancellationToken cancellationToken); protected virtual bool shouldReconnect(WebSocketMessage closingMessage) { return true; } } internal readonly struct WebSocketMessage { public readonly ArraySegment<byte> MessageData; public readonly WebSocketCloseStatus? CloseStatus; public readonly string CloseStatusDescription; public readonly WebSocketMessageType MessageType; public WebSocketMessage(ArraySegment<byte> messageData, WebSocketReceiveResult result) { MessageData = messageData; CloseStatus = result.CloseStatus; CloseStatusDescription = result.CloseStatusDescription; MessageType = result.MessageType; } } } namespace RiskOfTwitch.User { public sealed class GetUsersResponse { public static GetUsersResponse Empty { get; } = new GetUsersResponse { Users = Array.Empty<TwitchUserData>() }; [JsonProperty("data")] public TwitchUserData[] Users { get; set; } = Array.Empty<TwitchUserData>(); } public sealed class TwitchUserData { [JsonProperty("id")] public string UserId { get; set; } [JsonProperty("login")] public string UserLoginName { get; set; } [JsonProperty("display_name")] public string UserDisplayName { get; set; } [JsonProperty("type")] public string UserType { get; set; } [JsonProperty("broadcaster_type")] public string BroadcasterType { get; set; } [JsonProperty("description")] public string UserDescription { get; set; } [JsonProperty("profile_image_url")] public string ProfileImageURL { get; set; } [JsonProperty("offline_image_url")] public string OfflineImageURL { get; set; } [JsonProperty("email")] public string UserEmail { get; set; } [JsonProperty("created_at")] public string UserCreatedAt { get; set; } } } namespace RiskOfTwitch.Logging { internal sealed class ConsoleLogSource : ILogSource { public void Log(object message, LogType type) { if (type != 0) { Console.WriteLine(message); } } } public interface ILogSource { void Log(object message, LogType type); } public enum LogType { Debug, Info, Message, Warning, Error, Fatal } } namespace RiskOfTwitch.EventSub { public enum ConnectionErrorType { FailedRetrieveUser, FailedEventSubscribe, TokenAuthenticationFailed, TokenInvalid, Generic } public sealed class ConnectionErrorEventArgs : EventArgs { public ConnectionErrorType Type { get; } public ConnectionErrorEventArgs(ConnectionErrorType type) { Type = type; } } internal interface ITwitchEventSubMessageHandler { Task HandleEventAsync(JToken deserializedEvent, CancellationToken cancellationToken); } public sealed class TokenAccessRevokedEventData { public readonly string SubscriptionType; public readonly string Status; public TokenAccessRevokedEventData(string subscriptionType, string status) { SubscriptionType = subscriptionType; Status = status; } } public sealed class TwitchEventSubClient : ITwitchEventSubMessageHandler { private readonly string _accessToken; private readonly string _overrideBroadcasterName; private readonly HashSet<string> _handledMessageIDs = new HashSet<string>(); private readonly HashSet<string> _activeSubscriptions = new HashSet<string>(); private CancellationTokenSource _disconnectedTokenSource = new CancellationTokenSource(); private TwitchEventSubConnection _mainConnection; private TwitchEventSubConnection _migratingConnection; private string _sessionID; public string ConnectedToChannel { get; private set; } public bool IsConnecting { get { if (_mainConnection != null) { return _mainConnection.State.GetValueOrDefault() == WebSocketState.Connecting; } return false; } } public bool HasConnection { get { if (_mainConnection != null) { return _mainConnection.State.GetValueOrDefault() == WebSocketState.Open; } return false; } } public bool IsFullyConnected { get { if (!string.IsNullOrEmpty(_sessionID)) { return _activeSubscriptions.Count > 0; } return false; } } public bool IsMigrating => _migratingConnection != null; public event EventHandler<ChannelChatMessageEvent> OnChannelChatMessage; public event EventHandler<ChannelChatNotificationEvent> OnChannelChatNotification; public event EventHandler<TokenAccessRevokedEventData> OnTokenAccessRevoked; public event EventHandler OnFullyConnected; public event EventHandler<ConnectionErrorEventArgs> OnConnectionError; public TwitchEventSubClient(string accessToken, string overrideBroadcasterName) { _accessToken = accessToken; _overrideBroadcasterName = overrideBroadcasterName; } public Task Connect(CancellationToken cancellationToken = default(CancellationToken)) { return Connect(new Uri("wss://eventsub.wss.twitch.tv/ws"), cancellationToken); } public async Task Connect(Uri uri, CancellationToken cancellationToken = default(CancellationToken)) { _disconnectedTokenSource?.Dispose(); _disconnectedTokenSource = new CancellationTokenSource(); using CancellationTokenSource cancelledOrDisconnectedSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _disconnectedTokenSource.Token); if (_mainConnection == null) { _mainConnection = new TwitchEventSubConnection(uri, this); await _mainConnection.Connect(cancelledOrDisconnectedSource.Token).ConfigureAwait(continueOnCapturedContext: false); } else { _mainConnection.ConnectionUrl = uri; await _mainConnection.Reconnect(TimeSpan.FromSeconds(0.5), cancelledOrDisconnectedSource.Token).ConfigureAwait(continueOnCapturedContext: false); } } public async Task Disconnect(CancellationToken cancellationToken = default(CancellationToken)) { _disconnectedTokenSource.Cancel(); if (_mainConnection != null) { await _mainConnection.Disconnect(cancellationToken); _mainConnection?.Dispose(); _mainConnection = null; } if (_migratingConnection != null) { await _migratingConnection.Disconnect(cancellationToken); _migratingConnection?.Dispose(); _migratingConnection = null; } if (_activeSubscriptions.Count <= 0) { return; } foreach (string subscriptionId in _activeSubscriptions) { using HttpClient httpClient = new HttpClient(); httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + _accessToken); httpClient.DefaultRequestHeaders.Add("Client-Id", "2h96zmad9nhz11unv407c9ou6i6ofj"); httpClient.DeleteAsync("https://api.twitch.tv/helix/eventsub/subscriptions?id=" + subscriptionId, cancellationToken).ContinueWith(delegate(Task<HttpResponseMessage> task) { if (!task.IsCanceled) { if (!task.IsFaulted) { using (HttpResponseMessage httpResponseMessage = task.Result) { if (!httpResponseMessage.IsSuccessStatusCode) { Log.Error($"Unable to delete subscription {subscriptionId}: {httpResponseMessage.StatusCode:D} {httpResponseMessage.ReasonPhrase}", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\EventSub\\TwitchEventSubClient.cs", "Disconnect", 126); } return; } } Log.Error(task.Exception, "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\EventSub\\TwitchEventSubClient.cs", "Disconnect", 118); } }); } _activeSubscriptions.Clear(); } private void beginMigration(string reconnectUrl) { _migratingConnection = new TwitchEventSubConnection(new Uri(reconnectUrl), this); _migratingConnection.Connect(); } public async Task HandleEventAsync(JToken jsonObject, CancellationToken cancellationToken) { JToken val = jsonObject.SelectToken("metadata.message_id", false); if (val == null) { Log.Error("Could not deserialize message_id property", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\EventSub\\TwitchEventSubClient.cs", "HandleEventAsync", 153); } else { if (!_handledMessageIDs.Add(val.ToObject<string>())) { return; } JToken val2 = jsonObject.SelectToken("metadata.message_type", false); if (val2 != null) { using (CancellationTokenSource cancelledOrDisconnectedSource = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken, _disconnectedTokenSource.Token)) { string text = val2.ToObject<string>(); switch (text) { case "session_welcome": await handleSessionWelcomeMessage(jsonObject, cancelledOrDisconnectedSource.Token); break; case "notification": handleNotificationMessage(jsonObject); break; case "session_reconnect": handleSessionReconnectMessage(jsonObject); break; case "revocation": handleRevokeMessageAsync(jsonObject); break; default: Log.Warning("Unhandled message type: " + text, "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\EventSub\\TwitchEventSubClient.cs", "HandleEventAsync", 188); break; case "session_keepalive": break; } return; } } Log.Error("Could not deserialize message_type property", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\EventSub\\TwitchEventSubClient.cs", "HandleEventAsync", 163); } } private void handleSessionReconnectMessage(JToken jsonObject) { //IL_0035: Expected O, but got Unknown JToken val = jsonObject.SelectToken("payload.session", false); if (val == null) { Log.Error("Could not deserialize session data", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\EventSub\\TwitchEventSubClient.cs", "handleSessionReconnectMessage", 198); return; } WebSocketSessionData webSocketSessionData; try { webSocketSessionData = val.ToObject<WebSocketSessionData>(); } catch (JsonException val2) { JsonException arg = val2; Log.Error_NoCallerPrefix($"Failed to deserialize session object: {arg}"); return; } beginMigration(webSocketSessionData.ReconnectUrl); } private void handleRevokeMessageAsync(JToken jsonObject) { string text = null; string text2 = null; JToken val = jsonObject.SelectToken("payload.subscription", false); if (val != null) { JToken val2 = val.SelectToken("type", false); if (val2 != null) { text = val2.ToObject<string>(); } JToken val3 = val.SelectToken("status", false); if (val3 != null) { text2 = val3.ToObject<string>(); } } this.OnTokenAccessRevoked?.Invoke(this, new TokenAccessRevokedEventData(text ?? string.Empty, text2 ?? string.Empty)); } private async Task handleSessionWelcomeMessage(JToken jsonObject, CancellationToken cancellationToken) { JToken val = jsonObject.SelectToken("payload.session", false); if (val == null) { Log.Error("Could not deserialize session data", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\EventSub\\TwitchEventSubClient.cs", "handleSessionWelcomeMessage", 247); this.OnConnectionError?.Invoke(this, new ConnectionErrorEventArgs(ConnectionErrorType.Generic)); return; } WebSocketSessionData webSocketSessionData; try { webSocketSessionData = val.ToObject<WebSocketSessionData>(); } catch (JsonException val2) { JsonException arg = val2; Log.Error_NoCallerPrefix($"Failed to deserialize session object: {arg}"); this.OnConnectionError?.Invoke(this, new ConnectionErrorEventArgs(ConnectionErrorType.Generic)); return; } if (IsMigrating) { if (_mainConnection != null) { _mainConnection.Dispose(); _mainConnection = null; } _mainConnection = _migratingConnection; return; } _sessionID = webSocketSessionData.SessionID; Result<AuthenticationTokenValidationResponse> result = await Authentication.GetAccessTokenValidationAsync(_accessToken, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (!result.IsSuccess) { ConnectionErrorType type = ConnectionErrorType.TokenAuthenticationFailed; if (result.Exception is InvalidAccessTokenException) { type = ConnectionErrorType.TokenInvalid; } this.OnConnectionError?.Invoke(this, new ConnectionErrorEventArgs(type)); return; } AuthenticationTokenValidationResponse value = result.Value; string userId = value.UserID; string broadcasterId = userId; string broadcasterName = value.Username; if (!string.IsNullOrEmpty(_overrideBroadcasterName)) { Result<GetUsersResponse> result2 = await StaticTwitchAPI.GetUsers(_accessToken, Array.Empty<string>(), new string[1] { _overrideBroadcasterName }, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (result2.IsSuccess) { broadcasterName = _overrideBroadcasterName; broadcasterId = result2.Value.Users[0].UserId; } else { Log.Error($"Failed to retrieve override broadcaster data {result2.Exception}", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\EventSub\\TwitchEventSubClient.cs", "handleSessionWelcomeMessage", 366); } } ConnectedToChannel = broadcasterName; bool flag = true; bool flag2 = flag; flag = flag2 & await sendSubscription<<>f__AnonymousType0<string, string, <>f__AnonymousType1<string, string>, <>f__AnonymousType2<string, string>>>(new { type = "channel.chat.message", version = "1", condition = new { broadcaster_user_id = broadcasterId, user_id = userId }, transport = new { method = "websocket", session_id = _sessionID } }, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); flag2 = flag; if (flag2 & await sendSubscription<<>f__AnonymousType0<string, string, <>f__AnonymousType1<string, string>, <>f__AnonymousType2<string, string>>>(new { type = "channel.chat.notification", version = "1", condition = new { broadcaster_user_id = broadcasterId, user_id = userId }, transport = new { method = "websocket", session_id = _sessionID } }, cancellationToken).ConfigureAwait(continueOnCapturedContext: false)) { this.OnFullyConnected?.Invoke(this, EventArgs.Empty); } else { this.OnConnectionError?.Invoke(this, new ConnectionErrorEventArgs(ConnectionErrorType.FailedEventSubscribe)); } async Task<bool> sendSubscription<T>(T message, CancellationToken cancellationToken) { using HttpClient client = new HttpClient(); client.DefaultRequestHeaders.Add("Authorization", "Bearer " + _accessToken); client.DefaultRequestHeaders.Add("Client-Id", "2h96zmad9nhz11unv407c9ou6i6ofj"); StringContent stringContent = new StringContent(JsonConvert.SerializeObject((object)message)); stringContent.Headers.ContentType = new MediaTypeHeaderValue("application/json"); using HttpResponseMessage subscribeResponseMessage = await client.PostAsync("https://api.twitch.tv/helix/eventsub/subscriptions", stringContent, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); if (!subscribeResponseMessage.IsSuccessStatusCode) { Log.Error($"Subscribe failed: {subscribeResponseMessage.StatusCode:D} ({subscribeResponseMessage.StatusCode:G}) {subscribeResponseMessage.ReasonPhrase}", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\EventSub\\TwitchEventSubClient.cs", "handleSessionWelcomeMessage", 309); return false; } using StreamReader responseReader = new StreamReader(await subscribeResponseMessage.Content.ReadAsStreamAsync().ConfigureAwait(continueOnCapturedContext: false), Encoding.UTF8); JsonReader responseJsonReader = (JsonReader)new JsonTextReader((TextReader)responseReader); try { _ = 2; JToken val3; try { val3 = await JToken.ReadFromAsync(responseJsonReader, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } catch (JsonException val4) { JsonException arg2 = val4; Log.Error($"Failed to deserialize subscribe response: {arg2}", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\EventSub\\TwitchEventSubClient.cs", "handleSessionWelcomeMessage", 329); return false; } JToken obj = val3.SelectToken("data", false); JArray val5 = (JArray)(object)((obj is JArray) ? obj : null); if (val5 == null || ((JContainer)val5).Count <= 0) { Log.Error("Subscribe response contained invalid data", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\EventSub\\TwitchEventSubClient.cs", "handleSessionWelcomeMessage", 336); return false; } JToken val6 = val5[0].SelectToken("id"); if (val6 == null) { Log.Error("Could not find subscription id", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\EventSub\\TwitchEventSubClient.cs", "handleSessionWelcomeMessage", 343); return false; } _activeSubscriptions.Add(val6.ToObject<string>()); return true; } finally { ((IDisposable)responseJsonReader)?.Dispose(); } } } private void handleNotificationMessage(JToken jsonObject) { JToken val = jsonObject.SelectToken("payload.subscription.type", false); if (val == null) { Log.Error("Failed to find subscription type", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\EventSub\\TwitchEventSubClient.cs", "handleNotificationMessage", 421); return; } string text = val.ToObject<string>(); if (!(text == "channel.chat.message")) { if (text == "channel.chat.notification") { handleChannelChatNotificationNotification(jsonObject); } else { Log.Warning("Unhandled notification message: " + text, "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\EventSub\\TwitchEventSubClient.cs", "handleNotificationMessage", 435); } } else { handleChannelChatMessageNotification(jsonObject); } } private void handleChannelChatMessageNotification(JToken jsonObject) { //IL_003d: Expected O, but got Unknown if (this.OnChannelChatMessage == null) { return; } JToken val = jsonObject.SelectToken("payload.event"); if (val == null) { Log.Error("Failed to find event object", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\EventSub\\TwitchEventSubClient.cs", "handleChannelChatMessageNotification", 448); return; } ChannelChatMessageEvent e; try { e = val.ToObject<ChannelChatMessageEvent>(); } catch (JsonException val2) { JsonException arg = val2; Log.Error_NoCallerPrefix($"Failed to deserialize chat message: {arg}"); return; } this.OnChannelChatMessage?.Invoke(this, e); } private void handleChannelChatNotificationNotification(JToken jsonObject) { //IL_003d: Expected O, but got Unknown if (this.OnChannelChatNotification == null) { return; } JToken val = jsonObject.SelectToken("payload.event"); if (val == null) { Log.Error("Failed to find event object", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\EventSub\\TwitchEventSubClient.cs", "handleChannelChatNotificationNotification", 474); return; } ChannelChatNotificationEvent e; try { e = val.ToObject<ChannelChatNotificationEvent>(); } catch (JsonException val2) { JsonException arg = val2; Log.Error_NoCallerPrefix($"Failed to deserialize chat notification: {arg}"); return; } this.OnChannelChatNotification?.Invoke(this, e); } } internal sealed class TwitchEventSubConnection : ClientWebSocketConnection { private readonly ITwitchEventSubMessageHandler _eventHandler; public TwitchEventSubConnection(Uri url, ITwitchEventSubMessageHandler eventHandler) : base(url) { _eventHandler = eventHandler; } protected override async Task handleSocketMessageAsync(WebSocketMessage message, CancellationToken cancellationToken) { if (message.MessageType != 0) { Log.Warning($"Unhandled socket message type: {message.MessageType}", "D:\\Git\\RiskOfChaos\\Solution\\RiskOfTwitch\\EventSub\\TwitchEventSubConnection.cs", "handleSocketMessageAsync", 32); return; } using MemoryStream memoryStream = new MemoryStream(message.MessageData.Array, message.MessageData.Offset, message.MessageData.Count); using StreamReader streamReader = new StreamReader(memoryStream, Encoding.UTF8); JsonTextReader jsonReader = new JsonTextReader((TextReader)streamReader); try { JToken deserializedMessage; try { deserializedMessage = await JToken.ReadFromAsync((JsonReader)(object)jsonReader, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); } catch (JsonException val) { JsonException arg = val; Log.Error_NoCallerPrefix($"Failed to deserialize web socket message: {arg}"); return; } Task.Run(async delegate { await _eventHandler.HandleEventAsync(deserializedMessage, cancellationToken).ConfigureAwait(continueOnCapturedContext: false); }); } finally { ((IDisposable)jsonReader)?.Dispose(); } } protected override bool shouldReconnect(WebSocketMessage closingMessage) { if (closingMessage.CloseStatus.HasValue) { switch (closingMessage.CloseStatus.Value) { case (WebSocketCloseStatus)4003: case (WebSocketCloseStatus)4004: return false; } } return base.shouldReconnect(closingMessage); } } [Serializable] public sealed class WebSocketSessionData { [JsonProperty("id")] public string SessionID { get; set; } [JsonProperty("status")] public string Status { get; set; } [JsonProperty("connected_at")] public string ConnectedAt { get; set; } [JsonProperty("keepalive_timeout_seconds")] public int? KeepaliveTimeoutSeconds { get; set; } [JsonProperty("reconnect_url")] public string ReconnectUrl { get; set; } } } namespace RiskOfTwitch.Emotes { public sealed class EmoteSetEmoteData { [JsonProperty("id")] public string EmoteId { get; set; } [JsonProperty("name")] public string EmoteName { get; set; } [JsonProperty("images")] public EmoteSetEmoteImageData ImageData { get; set; } [JsonProperty("emote_type")] public string EmoteType { get; set; } [JsonProperty("emote_set_id")] public string EmoteSetId { get; set; } [JsonProperty("owner_id")] public string EmoteOwnerId { get; set; } [JsonProperty("format")] public string[] EmoteFormats { get; set; } [JsonProperty("scale")] public string[] Scales { get; set; } [JsonProperty("theme_mode")] public string[] ThemeModes { get; set; } } public sealed class EmoteSetEmoteImageData { [JsonProperty("url_1x")] public string SmallUrl { get; set; } [JsonProperty("url_2x")] public string MediumUrl { get; set; } [JsonProperty("url_4x")] public string LargeUrl { get; set; } } public sealed class GetEmoteSetResponse { public static GetEmoteSetResponse Empty { get; } = new GetEmoteSetResponse { Emotes = Array.Empty<EmoteSetEmoteData>(), UrlTemplate = string.Empty }; [JsonProperty("data")] public EmoteSetEmoteData[] Emotes { get; set; } [JsonProperty("template")] public string UrlTemplate { get; set; } public bool TryFindEmote(string emoteId, out EmoteSetEmoteData emote) { EmoteSetEmoteData[] emotes = Emotes; foreach (EmoteSetEmoteData emoteSetEmoteData in emotes) { if (string.Equals(emoteSetEmoteData.EmoteId, emoteId, StringComparison.Ordinal)) { emote = emoteSetEmoteData; return true; } } emote = null; return false; } public string GetEmoteFetchUrl(EmoteSetEmoteData emote, string format, string theme, string scale) { return UrlTemplate.Replace("{{id}}", emote.EmoteId).Replace("{{format}}", format).Replace("{{theme_mode}}", theme) .Replace("{{scale}}", scale); } } } namespace RiskOfTwitch.Chat { public sealed class ChannelChatClearUserMessagesEvent { [JsonProperty("broadcaster_user_id")] public string BroadcasterUserId { get; set; } [JsonProperty("broadcaster_user_name")] public string BroadcasterDisplayName { get; set; } [JsonProperty("broadcaster_user_login")] public string BroadcasterLoginName { get; set; } [JsonProperty("target_user_id")] public string TargetUserId { get; set; } [JsonProperty("target_user_name")] public string TargetUserDisplayName { get; set; } [JsonProperty("target_user_login")] public string TargetUserLoginName { get; set; } } public sealed class ChatterBadgeData { [JsonProperty("set_id")] public string BadgeSetID { get; set; } [JsonProperty("id")] public string BadgeID { get; set; } [JsonProperty("info")] public string BadgeMetadata { get; set; } } } namespace RiskOfTwitch.Chat.Notification { public sealed class ChannelChatAnnouncementNotificationData { [JsonProperty("color")] public string Color { get; set; } } public sealed class ChannelChatBitsBadgeTierNotificationData { [JsonProperty("tier")] public int Tier { get; set; } } public sealed class ChannelChatCharityDonationAmountData { [JsonProperty("value")] public int Value { get; set; } [JsonProperty("decimal_place")] public int DecimalPlace { get; set; } [JsonProperty("currency")] public string CurrencyCode { get; set; } } public sealed class ChannelChatCharityDonationNotificationData { [JsonProperty("charity_name")] public string CharityName { get; set; } [JsonProperty("amount")] public ChannelChatCharityDonationAmountData Amount { get; set; } } public sealed class ChannelChatCommunitySubGiftNotificationData { [JsonProperty("id")] public string Id { get; set; } [JsonProperty("total")] public int Amount { get; set; } [JsonProperty("sub_tier")] public string SubTier { get; set; } [JsonProperty("cumulative_total")] public int? TotalGiftedByUser { get; set; } } public sealed class ChannelChatGiftPaidUpgradeNotificationData { [JsonProperty("gifter_is_anonymous")] public bool GifterIsAnonymous { get; set; } [JsonProperty("gifter_user_id")] public string GifterUserId { get; set; } [JsonProperty("gifter_user_name")] public string GifterDisplayName { get; set; } [JsonProperty("gifter_user_login")] public string GifterLoginName { get; set; } } public sealed class ChannelChatNotificationEvent { [JsonProperty("broadcaster_user_id")] public string BroadcasterUserId { get; set; } [JsonProperty("broadcaster_user_name")] public string BroadcasterDisplayName { get; set; } [JsonProperty("broadcaster_user_login")] public string BroadcasterLoginName { get; set; } [JsonProperty("chatter_user_id")] public string ChatterUserId { get; set; } [JsonProperty("chatter_user_name")] public string ChatterDisplayName { get; set; } [JsonProperty("chatter_user_login")] public string ChatterLoginName { get; set; } [JsonProperty("chatter_is_anonymous")] public bool AnonymousChatter { get; set; } [JsonProperty("color")] public string ChatterNameColor { get; set; } [JsonProperty("badges")] public ChatterBadgeData[] Badges { get; set; } [JsonProperty("system_message")] public string SystemMessage { get; set; } [JsonProperty("message_id")] public string MessageId { get; set; } [JsonProperty("message")] public ChannelChatMessageData MessageData { get; set; } [JsonProperty("notice_type")] public string NoticeType { get; set; } [JsonProperty("sub")] public ChannelChatSubNotificationData SubData { get; set; } [JsonProperty("resub")] public ChannelChatResubNotificationData ResubData { get; set; } [JsonProperty("sub_gift")] public ChannelChatSubGiftNotificationData SubGiftData { get; set; } [JsonProperty("community_sub_gift")] public ChannelChatCommunitySubGiftNotificationData CommunitySubGiftData { get; set; } [JsonProperty("gift_paid_upgrade")] public ChannelChatGiftPaidUpgradeNotificationData GiftPaidUpgradeData { get; set; } [JsonProperty("prime_paid_upgrade")] public ChannelChatPrimePaidUpgradeNotificationData PrimePaidUpgradeData { get; set; } [JsonProperty("raid")] public ChannelChatRaidNotificationData RaidData { get; set; } [JsonProperty("unraid")] public ChannelChatUnraidNotificationData UnraidData { get; set; } [JsonProperty("pay_it_forward")] public ChannelChatPayItForwardNotificationData PayItForwardData { get; set; } [JsonProperty("announcement")] public ChannelChatAnnouncementNotificationData AnnouncementData { get; set; } [JsonProperty("charity_donation")] public ChannelChatCharityDonationNotificationData CharityDonationData { get; set; } [JsonProperty("bits_badge_tier")] public ChannelChatBitsBadgeTierNotificationData ChatBitsBadgeTierData { get; set; } } public sealed class ChannelChatPayItForwardNotificationData { [JsonProperty("gifter_is_anonymous")] public bool GifterIsAnonymous { get; set; } [JsonProperty("gifter_user_id")] public string GifterUserId { get; set; } [JsonProperty("gifter_user_name")] public string GifterDisplayName { get; set; } [JsonProperty("gifter_user_login")] public string GifterLoginName { get; set; } } public sealed class ChannelChatPrimePaidUpgradeNotificationData { [JsonProperty("sub_tier")] public string Tier { get; set; } } public sealed class ChannelChatRaidNotificationData { [JsonProperty("user_id")] public string RaiderUserId { get; set; } [JsonProperty("user_name")] public string RaiderDisplayName { get; set; } [JsonProperty("user_login")] public string RaiderLoginName { get; set; } [JsonProperty("viewer_count")] public int NumViewers { get; set; } [JsonProperty("profile_image_url")] public string RaiderProfileImageUrl { get; set; } } public sealed class ChannelChatResubNotificationData { [JsonProperty("cumulative_months")] public int CumulativeMonths { get; set; } [JsonProperty("duration_months")] public int DurationMonths { get; set; } [JsonProperty("streak_months")] public int? StreakMonths { get; set; } [JsonProperty("sub_tier")] public string Tier { get; set; } [JsonProperty("is_prime")] public bool? IsPrime { get; set; } [JsonProperty("is_gift")] public bool IsGifted { get; set; } [JsonProperty("gifter_is_anonymous")] public bool? GifterIsAnonymous { get; set; } [JsonProperty("gifter_user_id")] public string GifterUserId { get; set; } [JsonProperty("gifter_user_name")] public string GifterDisplayName { get; set; } [JsonProperty("gifter_user_login")] public string GifterLoginName { get; set; } } public sealed class ChannelChatSubGiftNotificationData { [JsonProperty("duration_months")] public int DurationMonths { get; set; } [JsonProperty("cumulative_total")] public int? TotalSubsGivenByUser { get; set; } [JsonProperty("recipient_user_id")] public string RecipientUserId { get; set; } [JsonProperty("recipient_user_name")] public string RecipientDisplayName { get; set; } [JsonProperty("recipient_user_login")] public string RecipientLoginName { get; set; } [JsonProperty("sub_tier")] public string SubTier { get; set; } [JsonProperty("community_gift_id")] public string CommunityGiftId { get; set; } } public sealed class ChannelChatSubNotificationData { [JsonProperty("sub_tier")] public string Tier { get; set; } [JsonProperty("is_prime")] public bool IsPrime { get; set; } [JsonProperty("duration_months")] public int DurationMonths { get; set; } } public sealed class ChannelChatUnraidNotificationData { } } namespace RiskOfTwitch.Chat.Message { public sealed class ChannelChatMessageData { [JsonProperty("text")] public string FullText { get; set; } [JsonProperty("fragments")] public ChatMessageFragment[] Fragments { get; set; } } public sealed class ChannelChatMessageEvent { [JsonProperty("broadcaster_user_id")] public string BroadcasterUserId { get; set; } [JsonProperty("broadcaster_user_name")] public string BroadcasterDisplayName { get; set; } [JsonProperty("broadcaster_user_login")] public string BroadcasterLoginName { get; set; } [JsonProperty("chatter_user_id")] public string ChatterUserId { get; set; } [JsonProperty("chatter_user_name")] public string ChatterDisplayName { get; set; } [JsonProperty("chatter_user_login")] public string ChatterLoginName { get; set; } [JsonProperty("message")] public ChannelChatMessageData MessageData { get; set; } [JsonProperty("message_type")] public string MessageType { get; set; } [JsonProperty("badges")] public ChatterBadgeData[] UserBadges { get; set; } [JsonProperty("cheer")] public ChatMessageCheerData CheerData { get; set; } [JsonProperty("color")] public string UserColor { get; set; } [JsonProperty("reply")] public ChatMessageReplyData ReplyData { get; set; } [JsonProperty("channel_points_custom_reward_id")] public string ChannelPointRedeemID { get; set; } } public sealed class ChatMessageCheerData { [JsonProperty("bits")] public int TotalBits { get; set; } } public sealed class ChatMessageCheermoteData { [JsonProperty("prefix")] public string Prefix { get; set; } [JsonProperty("bits")] public int BitAmount { get; set; } [JsonProperty("tier")] public int Tier { get; set; } } public sealed class ChatMessageEmoteData { private static readonly string[] _emoteModificationSuffixes = new string[5] { "_BW", "_HF", "_SG", "_SQ", "_TK" }; private string _emoteID; [JsonProperty("id")] public string EmoteID { get { return _emoteID; } set { _emoteID = value; string text = _emoteID; string[] emoteModificationSuffixes = _emoteModificationSuffixes; foreach (string text2 in emoteModificationSuffixes) { if (text.EndsWith(text2)) { text = text.Remove(text.Length - text2.Length); break; } } BaseEmoteID = text; } } [JsonIgnore] public string BaseEmoteID { get; private set; } [JsonProperty("emote_set_id")] public string EmoteSetID { get; set; } [JsonProperty("owner_id")] public string EmoteOwnerUserID { get; set; } [JsonProperty("format")] public string[] EmoteTypes { get; set; } } public sealed class ChatMessageFragment { [JsonProperty("type")] public string FragmentType { get; set; } [JsonProperty("text")] public string FragmentText { get; set; } [JsonProperty("cheermote")] public ChatMessageCheermoteData CheermoteData { get; set; } [JsonProperty("emote")] public ChatMessageEmoteData EmoteData { get; set; } [JsonProperty("mention")] public ChatMessageMentionData MentionData { get; set; } } public sealed class ChatMessageMentionData { [JsonProperty("user_id")] public string MentionedUserID { get; set; } [JsonProperty("user_name")] public string MentionedUserDisplayName { get; set; } [JsonProperty("user_login")] public string MentionedUserLoginName { get; set; } } public sealed class ChatMessageReplyData { [JsonProperty("parent_message_id")] public string ReplyingToMessageID { get; set; } [JsonProperty("parent_message_body")] public string ReplyingToMessageBody { get; set; } [JsonProperty("parent_user_id")] public string ReplyingToUserID { get; set; } [JsonProperty("parent_user_name")] public string ReplyingToUserDisplayName { get; set; } [JsonProperty("parent_user_login")] public string ReplyingToUserLoginName { get; set; } [JsonProperty("thread_message_id")] public string ThreadRootMessageID { get; set; } [JsonProperty("thread_user_id")] public string ThreadRootUserID { get; set; } [JsonProperty("thread_user_name")] public string ThreadRootUserDisplayName { get; set; } [JsonProperty("thread_user_login")] public string ThreadRootUserLoginName { get; set; } } }