Some mods may be broken due to the recent Alloyed Collective update.
Decompiled source of CurseCatcher v0.3.2
CurseCatcher.dll
Decompiled a year agousing System; using System.CodeDom.Compiler; using System.Collections.Generic; using System.ComponentModel; using System.Diagnostics; using System.Globalization; using System.Reflection; using System.Reflection.Emit; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security.Permissions; using BepInEx; using BepInEx.Configuration; using CurseCatcher.Properties; using HG; using HarmonyLib; using Microsoft.CodeAnalysis; using RoR2; using UnityEngine; using UnityEngine.Networking; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.3.2.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 CurseCatcher.Properties { [GeneratedCode("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] [DebuggerNonUserCode] [CompilerGenerated] internal class Resources { private static ResourceManager resourceMan; private static CultureInfo resourceCulture; [EditorBrowsable(EditorBrowsableState.Advanced)] internal static ResourceManager ResourceManager { get { if (resourceMan == null) { resourceMan = new ResourceManager("CurseCatcher.Properties.Resources", typeof(Resources).Assembly); } return resourceMan; } } [EditorBrowsable(EditorBrowsableState.Advanced)] internal static CultureInfo Culture { get { return resourceCulture; } set { resourceCulture = value; } } internal static byte[] disabled => (byte[])ResourceManager.GetObject("disabled", resourceCulture); internal static byte[] enabled => (byte[])ResourceManager.GetObject("enabled", resourceCulture); internal Resources() { } } } namespace Local.Eclipse.CurseCatcher { internal static class Artifact { private static ArtifactDef definition = null; private static int ruleIndex = -1; [HarmonyPatch(typeof(ArtifactCatalog), "SetArtifactDefs")] [HarmonyPostfix] private static void CreateArtifact() { //IL_0005: Unknown result type (might be due to invalid IL or missing references) //IL_000a: 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_0020: Unknown result type (might be due to invalid IL or missing references) //IL_0030: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005d: Expected O, but got Unknown //IL_007a: Unknown result type (might be due to invalid IL or missing references) //IL_0084: Expected O, but got Unknown //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_0094: Expected O, but got Unknown definition = new ArtifactDef { nameToken = "Artifact of Infliction", descriptionToken = "Only enemies inflict permanent damage.", smallIconSelectedSprite = Load(Resources.enabled), smallIconDeselectedSprite = Load(Resources.disabled), artifactIndex = (ArtifactIndex)ArtifactCatalog.artifactDefs.Length, cachedName = "Curse" }; ArrayUtils.ArrayAppend<ArtifactDef>(ref ArtifactCatalog.artifactDefs, ref definition); Harmony instance = null; RunArtifactManager.onArtifactEnabledGlobal += (ArtifactStateChangeDelegate)delegate(RunArtifactManager _, ArtifactDef artifact) { if (instance == null && NetworkServer.active && (Object)(object)artifact == (Object)(object)definition) { instance = Harmony.CreateAndPatchAll(Plugin.instance.GetType(), (string)null); } }; RunArtifactManager.onArtifactDisabledGlobal += (ArtifactStateChangeDelegate)delegate(RunArtifactManager _, ArtifactDef artifact) { if ((Object)(object)artifact == (Object)(object)definition) { Harmony obj = instance; if (obj != null) { obj.UnpatchSelf(); } instance = null; } }; } private static Sprite Load(byte[] imageData) { //IL_000d: Unknown result type (might be due to invalid IL or missing references) //IL_0013: Expected O, but got Unknown //IL_0034: 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) Texture2D val = new Texture2D(512, 512, (TextureFormat)5, 4, false); ImageConversion.LoadImage(val, imageData); return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2((float)(((Texture)val).width / 2), (float)(((Texture)val).height / 2))); } [HarmonyPatch(typeof(RuleCatalog), "Init")] [HarmonyFinalizer] private static void AddArtifact(Exception __exception) { //IL_000a: Unknown result type (might be due to invalid IL or missing references) if (__exception != null) { throw __exception; } RuleDef val = RuleDef.FromArtifact(definition.artifactIndex); ruleIndex = RuleCatalog.allRuleDefs.Count; val.globalIndex = ruleIndex; RuleCatalog.allRuleDefs.Add(val); RuleCatalog.ruleDefsByGlobalName[val.globalName] = val; val.category = RuleCatalog.artifactRuleCategory; RuleCatalog.artifactRuleCategory.children.Add(val); for (int i = 0; i < val.choices.Count; i++) { RuleChoiceDef val2 = val.choices[i]; val2.localIndex = i; val2.globalIndex = RuleCatalog.allChoicesDefs.Count; RuleCatalog.allChoicesDefs.Add(val2); RuleCatalog.ruleChoiceDefsByGlobalName[val2.globalName] = val2; } } [HarmonyPatch(typeof(RuleCatalog), "AddRule")] [HarmonyPrefix] private static bool SkipRule(RuleDef ruleDef) { //IL_0015: Unknown result type (might be due to invalid IL or missing references) //IL_001f: Unknown result type (might be due to invalid IL or missing references) foreach (RuleChoiceDef choice in ruleDef.choices) { if (choice.artifactIndex == definition.artifactIndex) { return false; } } return true; } [HarmonyPatch(typeof(EclipseRun), "OverrideRuleChoices")] [HarmonyPostfix] private static void ShowInEclipse(RuleChoiceMask mustInclude, RuleChoiceMask mustExclude) { foreach (RuleChoiceDef item in (IEnumerable<RuleChoiceDef>)((ruleIndex >= 0) ? RuleCatalog.GetRuleDef(ruleIndex).choices : new List<RuleChoiceDef>())) { ((SerializableBitArray)mustInclude)[item.globalIndex] = false; ((SerializableBitArray)mustExclude)[item.globalIndex] = false; } } [HarmonyPatch(typeof(NetworkExtensions), "Write", new Type[] { typeof(NetworkWriter), typeof(RuleBook) })] [HarmonyPrefix] private static bool WriteRuleBook(NetworkWriter writer, RuleBook src) { for (int i = 0; i < src.ruleValues.Length; i++) { if (i != ruleIndex) { writer.Write(src.ruleValues[i]); } } return false; } [HarmonyPatch(typeof(NetworkExtensions), "ReadRuleBook")] [HarmonyPrefix] private static bool ReadRuleBook(NetworkReader reader, RuleBook dest) { for (int i = 0; i < dest.ruleValues.Length; i++) { if (i == ruleIndex) { dest.ruleValues[i] = (byte)RuleCatalog.GetRuleDef(ruleIndex).defaultChoiceIndex; } else { dest.ruleValues[i] = reader.ReadByte(); } } return false; } [HarmonyPatch(typeof(RunArtifactManager), "OnDeserialize")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> LimitReadLength(IEnumerable<CodeInstruction> IL) { MethodInfo readBitArray = typeof(NetworkExtensions).GetMethod("ReadBitArray", new Type[2] { typeof(NetworkReader), typeof(bool[]) }); foreach (CodeInstruction item in IL) { if (CodeInstructionExtensions.Calls(item, readBitArray)) { yield return Transpilers.EmitDelegate<Action<NetworkReader, bool[]>>((Action<NetworkReader, bool[]>)delegate(NetworkReader input, bool[] array) { if (definition == null) { NetworkExtensions.ReadBitArray(input, array); } else { NetworkExtensions.ReadBitArray(input, array, array.Length - 1); } }); } else { yield return item; } } } } [BepInPlugin("local.eclipse.cursecatcher", "CurseCatcher", "0.3.2")] internal class Plugin : BaseUnityPlugin { internal interface IPatch { object GetDamageType(DamageInfo info); } private class Hopoo : IPatch { [HarmonyPatch(typeof(HealthComponent), "TakeDamage")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpile(IEnumerable<CodeInstruction> IL) { return InsertCodeInstruction(IL); } public object GetDamageType(DamageInfo info) { return typeof(DamageInfo).GetField("damageType").GetValue(info); } } private class Gearbox : IPatch { [HarmonyPatch(typeof(HealthComponent), "TakeDamageProcess")] [HarmonyTranspiler] private static IEnumerable<CodeInstruction> Transpile(IEnumerable<CodeInstruction> IL) { return InsertCodeInstruction(IL); } public object GetDamageType(DamageInfo info) { //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) //IL_001c: Unknown result type (might be due to invalid IL or missing references) //IL_0026: Expected I4, but got Unknown //IL_000f: Unknown result type (might be due to invalid IL or missing references) DamageType damageType = info.damageType.damageType; if ((int)damageType != 0) { return damageType; } return (uint)(int)info.damageType.damageTypeExtended; } } public const string identifier = "local.eclipse.cursecatcher"; public const string version = "0.3.2"; private static bool artifact; private static ConfigEntry<bool> self; private static ConfigEntry<bool> friendly; private static ConfigEntry<bool> fall; private static ConfigEntry<bool> interactable; private static ConfigEntry<bool> hazard; private static ConfigEntry<bool> log; internal static IPatch instance; protected void Awake() { self = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Self Damage", false, "Abilities that cost health to activate will curse the player if this setting is enabled."); friendly = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Friendly Fire", true, "Effects that damage allies may apply curse when enabled."); fall = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Fall Damage", true, "Inflict curse upon taking sufficient fall damage."); interactable = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Interactable Cost", true, "Whether the debuff is triggered upon paying health costs."); hazard = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Neutral Hazards", true, "If neutral damage, such as stage hazards, can cause curse."); artifact = ((BaseUnityPlugin)this).Config.Bind<bool>("Other", "Artifact Enabled", false, "Used to toggle the above functionality. Selectable in the Eclipse lobby, but also applies the modifier to other game modes.").Value; log = ((BaseUnityPlugin)this).Config.Bind<bool>("Other", "Detailed Logging", false, "For troubleshooting purposes only."); if (artifact) { Harmony.CreateAndPatchAll(typeof(Artifact), (string)null); RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, new Action(CheckVersion)); return; } RoR2Application.onLoad = (Action)Delegate.Combine(RoR2Application.onLoad, (Action)delegate { CheckVersion(); Harmony.CreateAndPatchAll(instance.GetType(), (string)null); }); } private void CheckVersion() { IPatch patch2; if (!Version.TryParse(RoR2Application.GetBuildId(), out Version result) || !(result < new Version(1, 3))) { IPatch patch = new Gearbox(); patch2 = patch; } else { IPatch patch = new Hopoo(); patch2 = patch; } instance = patch2; } private static IEnumerable<CodeInstruction> InsertCodeInstruction(IEnumerable<CodeInstruction> IL) { MethodInfo getSelectedDifficulty = typeof(Run).GetProperty("selectedDifficulty").GetMethod; bool found = false; CodeInstruction previousInstruction = null; Console.WriteLine("Installing hook for 'Eclipse 8' curse..."); Label? label = default(Label?); foreach (CodeInstruction instruction in IL) { if (found && CodeInstructionExtensions.Branches(instruction, ref label)) { found = false; if (CodeInstructionExtensions.LoadsConstant(previousInstruction, (Enum)(object)(DifficultyIndex)10)) { Console.WriteLine("...instruction sequence found."); yield return new CodeInstruction(OpCodes.Pop, (object)null); yield return new CodeInstruction(OpCodes.Ldarg_1, (object)null); yield return CodeInstruction.Call(typeof(Plugin), "ApplyCurse", (Type[])null, (Type[])null); yield return new CodeInstruction(OpCodes.Brfalse, instruction.operand); continue; } } else if (CodeInstructionExtensions.Calls(instruction, getSelectedDifficulty)) { found = true; } previousInstruction = instruction; yield return instruction; } } public static bool ApplyCurse(DifficultyIndex difficulty, DamageInfo damageInfo) { //IL_0007: Unknown result type (might be due to invalid IL or missing references) //IL_000a: Invalid comparison between Unknown and I4 //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_0045: Unknown result type (might be due to invalid IL or missing references) //IL_0047: Invalid comparison between Unknown and I4 //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c5: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: 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_004b: Invalid comparison between Unknown and I4 //IL_00cb: Unknown result type (might be due to invalid IL or missing references) //IL_00ce: Invalid comparison between Unknown and I4 //IL_007a: Unknown result type (might be due to invalid IL or missing references) if (!artifact && (int)difficulty < 10) { return false; } bool flag = true; if (log.Value) { PrintInfo(damageInfo); } if (damageInfo.attacker == null) { object damageType = instance.GetDamageType(damageInfo); if (damageType is DamageType val) { if ((int)val == 1 || (int)val == 3) { goto IL_006a; } if (((Enum)val).HasFlag((Enum)(object)(DamageType)2097152)) { flag = fall.Value; } } else if (damageType is uint && (uint)damageType == 134217728) { goto IL_006a; } } else if (Object.op_Implicit((Object)(object)damageInfo.attacker)) { TeamComponent component = damageInfo.attacker.GetComponent<TeamComponent>(); if (Object.op_Implicit((Object)(object)component)) { TeamIndex teamIndex = component.teamIndex; if ((int)teamIndex != 0) { if ((int)teamIndex == 1) { flag = friendly.Value; } } else { flag = hazard.Value; } } else if (damageInfo.attacker.GetComponent<IInteractable>() != null) { flag = interactable.Value; } } goto IL_0102; IL_0102: if (flag) { return true; } if (log.Value) { Console.WriteLine("...preventing curse."); } return false; IL_006a: flag = self.Value; goto IL_0102; } private static void PrintInfo(DamageInfo damage) { //IL_0092: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Unknown result type (might be due to invalid IL or missing references) string text = getName(damage.attacker); string text2 = getName(damage.inflictor); string text3 = "attacker: " + text; if (text2 != text && damage.inflictor != null) { text3 = text3 + " (" + text2 + ")"; } if ((Object)(object)damage.attacker != (Object)null) { TeamComponent component = damage.attacker.GetComponent<TeamComponent>(); if ((Object)(object)component != (Object)null) { string text4 = text3; TeamIndex teamIndex = component.teamIndex; text3 = text4 + ", team: " + ((object)(TeamIndex)(ref teamIndex)).ToString(); } } string text5 = text3; DamageTypeCombo damageType = damage.damageType; text3 = text5 + ", type: " + ((object)(DamageTypeCombo)(ref damageType)).ToString(); Console.WriteLine(text3); static string getName(GameObject obj) { string text6 = ((obj == null) ? "null" : (((Object)(object)obj == (Object)null) ? "destroyed" : ((((Object)obj).name != null) ? ((Object)obj).name : "unknown"))); int num = text6.IndexOf('('); int num2 = text6.IndexOf(')') - num + 1; if (num >= 0 && num2 >= 0) { text6 = text6.Remove(num, num2); } return text6; } } } }