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 CurseCatcher v0.3.2
CurseCatcher.dll
Decompiled 2 years 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; } } } }