using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using HarmonyLib;
using Microsoft.CodeAnalysis;
[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("MadnessZeroChests")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.0.0")]
[assembly: AssemblyInformationalVersion("0.1.0")]
[assembly: AssemblyProduct("MadnessZeroChests")]
[assembly: AssemblyTitle("MadnessZeroChests")]
[assembly: AssemblyVersion("0.1.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
[CompilerGenerated]
[Embedded]
internal sealed class EmbeddedAttribute : Attribute
{
}
}
namespace System.Runtime.CompilerServices
{
[CompilerGenerated]
[Embedded]
[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
internal sealed class RefSafetyRulesAttribute : Attribute
{
public readonly int Version;
public RefSafetyRulesAttribute(int P_0)
{
Version = P_0;
}
}
}
namespace MadnessZeroChests
{
public static class ChestIl
{
public static readonly MethodInfo GetNgPlus = AccessTools.Method(typeof(AtOManager), "GetNgPlus", new Type[1] { typeof(bool) }, (Type[])null);
public static readonly MethodInfo Normalize = AccessTools.Method(typeof(ChestIl), "AsMadnessZero", (Type[])null, (Type[])null);
public static int AsMadnessZero(int actualMadness)
{
return 0;
}
public static List<CodeInstruction> NormalizeNgCalls(IEnumerable<CodeInstruction> instructions)
{
//IL_005e: Unknown result type (might be due to invalid IL or missing references)
//IL_0068: Expected O, but got Unknown
List<CodeInstruction> list = instructions.ToList();
List<CodeInstruction> list2 = list.Where((CodeInstruction i) => CodeInstructionExtensions.Calls(i, GetNgPlus)).ToList();
Require(list2.Count == 1, "Expected one chest-related GetNgPlus call.");
list.Insert(list.IndexOf(list2[0]) + 1, new CodeInstruction(OpCodes.Call, (object)Normalize));
return list;
}
public static List<CodeInstruction> NormalizeRunEligibility(IEnumerable<CodeInstruction> instructions)
{
//IL_006b: Unknown result type (might be due to invalid IL or missing references)
//IL_0075: Expected O, but got Unknown
List<CodeInstruction> list = instructions.ToList();
FieldInfo field = AccessTools.Field(typeof(PlayerRun), "MadnessLevel");
List<CodeInstruction> list2 = list.Where((CodeInstruction i) => CodeInstructionExtensions.LoadsField(i, field, false)).ToList();
Require(list2.Count == 1, "Expected one saved-run chest eligibility check.");
list.Insert(list.IndexOf(list2[0]) + 1, new CodeInstruction(OpCodes.Call, (object)Normalize));
return list;
}
public static List<CodeInstruction> NormalizeFinishReward(IEnumerable<CodeInstruction> instructions)
{
//IL_0238: Unknown result type (might be due to invalid IL or missing references)
//IL_0242: Expected O, but got Unknown
List<CodeInstruction> code = instructions.ToList();
int num = code.FindIndex((CodeInstruction i) => CodeInstructionExtensions.Calls(i, GetNgPlus));
Require(num >= 0 && code.Count((CodeInstruction i) => CodeInstructionExtensions.Calls(i, GetNgPlus)) == 1, "Expected one finish reward GetNgPlus call.");
int local = LocalIndex(code[num + 1], load: false);
Require(local >= 0, "Expected the actual Madness to be stored in a local.");
FieldInfo fieldInfo = AccessTools.Field(typeof(PlayerRun), "MadnessLevel");
List<int> list = (from i in Enumerable.Range(0, code.Count)
where LocalIndex(code[i], load: true) == local
select i).ToList();
Require(list.Count == 4, "Expected three reward checks and one history read.");
Require(CodeInstructionExtensions.LoadsConstant(code[list[0] + 1], 0L) && IsBranch(code[list[0] + 2], OpCodes.Ble, OpCodes.Ble_S), "Missing reward lower bound.");
Require(CodeInstructionExtensions.LoadsConstant(code[list[1] + 1], 3L) && IsBranch(code[list[1] + 2], OpCodes.Bge, OpCodes.Bge_S), "Missing reward upper bound.");
Require(CodeInstructionExtensions.LoadsConstant(code[list[2] + 1], 2L) && IsBranch(code[list[2] + 2], OpCodes.Bgt, OpCodes.Bgt_S), "Missing reward visibility bound.");
Require(CodeInstructionExtensions.StoresField(code[list[3] + 1], fieldInfo), "Actual Madness history write changed.");
foreach (int item in list.Take(3).Reverse())
{
code.Insert(item + 1, new CodeInstruction(OpCodes.Call, (object)Normalize));
}
return code;
}
private static bool IsBranch(CodeInstruction instruction, OpCode normal, OpCode shortForm)
{
if (!(instruction.opcode == normal))
{
return instruction.opcode == shortForm;
}
return true;
}
private static int LocalIndex(CodeInstruction i, bool load)
{
if (i.opcode == (load ? OpCodes.Ldloc_0 : OpCodes.Stloc_0))
{
return 0;
}
if (i.opcode == (load ? OpCodes.Ldloc_1 : OpCodes.Stloc_1))
{
return 1;
}
if (i.opcode == (load ? OpCodes.Ldloc_2 : OpCodes.Stloc_2))
{
return 2;
}
if (i.opcode == (load ? OpCodes.Ldloc_3 : OpCodes.Stloc_3))
{
return 3;
}
if (i.opcode != (load ? OpCodes.Ldloc : OpCodes.Stloc) && i.opcode != (load ? OpCodes.Ldloc_S : OpCodes.Stloc_S))
{
return -1;
}
if (i.operand is LocalBuilder localBuilder)
{
return localBuilder.LocalIndex;
}
if (i.operand is LocalVariableInfo localVariableInfo)
{
return localVariableInfo.LocalIndex;
}
return Convert.ToInt32(i.operand);
}
private static void Require(bool condition, string message)
{
if (!condition)
{
throw new InvalidOperationException("Madness Zero Chests: " + message);
}
}
}
[HarmonyPatch(typeof(TownManager), "ShowButtons")]
internal static class ChestVisibilityPatch
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
return ChestIl.NormalizeNgCalls(instructions);
}
}
[HarmonyPatch]
internal static class EarnedChestPatch
{
private static MethodBase TargetMethod()
{
return AccessTools.EnumeratorMoveNext((MethodBase)AccessTools.Method(typeof(TownManager), "SetTreasures", (Type[])null, (Type[])null));
}
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
return ChestIl.NormalizeRunEligibility(instructions);
}
}
[HarmonyPatch(typeof(CurrencyManager), "GetInitResources")]
internal static class SoloStartingResourcesPatch
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
return ChestIl.NormalizeNgCalls(instructions);
}
}
[HarmonyPatch(typeof(CurrencyManager), "GetInitResourcesMP")]
internal static class CoopStartingResourcesPatch
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
return ChestIl.NormalizeNgCalls(instructions);
}
}
[HarmonyPatch(typeof(FinishRunManager), "CalculateFinishRunReward")]
internal static class FinishRewardPatch
{
private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
{
return ChestIl.NormalizeFinishReward(instructions);
}
}
[HarmonyPatch(typeof(Functions), "GetMadnessBonusText")]
internal static class MadnessDescriptionPatch
{
private static void Postfix(int value, ref string __result)
{
if (value >= 3 && value <= 9)
{
string[] array = new string[7] { "800", "700", "600", "500", "400", "300", "250" };
string oldValue = string.Format(Texts.Instance.GetText("madnessNoChest", ""), array[value - 3]);
__result = __result.Replace(oldValue, "Starting chests and starting resources follow Madness 0 rules (mod).");
}
}
}
[BepInPlugin("cheyenne.acrosstheobelisk.madnesszerochests", "Madness Zero Chests", "0.1.0")]
[BepInProcess("AcrossTheObelisk.exe")]
public sealed class Plugin : BaseUnityPlugin
{
public const string Id = "cheyenne.acrosstheobelisk.madnesszerochests";
private Harmony harmony;
private void Awake()
{
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
//IL_0010: Expected O, but got Unknown
harmony = new Harmony("cheyenne.acrosstheobelisk.madnesszerochests");
try
{
harmony.PatchAll(typeof(Plugin).Assembly);
((BaseUnityPlugin)this).Logger.LogInfo((object)"Madness Zero Chests 0.1.0 active: Madness 0 chest/resource rules. Install on every co-op player.");
}
catch (Exception ex)
{
harmony.UnpatchSelf();
((BaseUnityPlugin)this).Logger.LogError((object)("Madness Zero Chests disabled: game code did not match expected patches. " + ex));
}
}
private void OnDestroy()
{
Harmony obj = harmony;
if (obj != null)
{
obj.UnpatchSelf();
}
}
}
}