Decompiled source of ScoutBadger v1.1.1

plugins/com.github.Kirshoo.ScoutBadger.dll

Decompiled 3 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using ScoutBadger.Configuration;
using ScoutBadger.Patches;
using ScoutBadger.Saves;
using ScoutBadger.UIHelpers;
using TMPro;
using UnityEngine;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("com.github.Kirshoo.ScoutBadger")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.1.1")]
[assembly: AssemblyProduct("com.github.Kirshoo.ScoutBadger")]
[assembly: AssemblyTitle("ScoutBadger")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.1.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 BepInEx
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class BepInAutoPluginAttribute : Attribute
	{
		public BepInAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace BepInEx.Preloader.Core.Patching
{
	[AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
	[Conditional("CodeGeneration")]
	internal sealed class PatcherAutoPluginAttribute : Attribute
	{
		public PatcherAutoPluginAttribute(string? id = null, string? name = null, string? version = null)
		{
		}
	}
}
namespace ScoutBadger
{
	[BepInPlugin("com.github.Kirshoo.ScoutBadger", "ScoutBadger", "1.1.1")]
	public class Plugin : BaseUnityPlugin
	{
		internal static SaveManager SaveManager;

		public const string Id = "com.github.Kirshoo.ScoutBadger";

		internal static ManualLogSource Log { get; private set; }

		public static string Name => "ScoutBadger";

		public static string Version => "1.1.1";

		private void Awake()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			BindConfig();
			SaveManager = new SaveManager(SaveConfig.SafeFile);
			SaveManager.Load();
			Harmony val = new Harmony("com.github.Kirshoo.ScoutBadger");
			val.PatchAll(typeof(AchievementManagerPatch));
			val.PatchAll(typeof(EndScreenPatch.BadgeRoutinePatch));
			val.PatchAll(typeof(BadgeUIPatch));
			Log.LogInfo((object)("Plugin " + Name + " is loaded!"));
		}

		private void OnApplicationQuit()
		{
			SaveManager.Save();
		}

		private void BindConfig()
		{
			SaveConfig.BindConfig(((BaseUnityPlugin)this).Config);
		}
	}
}
namespace ScoutBadger.UIHelpers
{
	internal class BadgeRepetitionText
	{
		private static TMP_FontAsset fontAsset;

		private const string fontname = "DarumaDropOne-Regular SDF";

		public const string RepetitionObjectName = "RepetitionText";

		public GameObject gameObject;

		private TextMeshProUGUI textComponent;

		private BadgeRepetitionText()
		{
		}

		public static BadgeRepetitionText CreateTextObject()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			BadgeRepetitionText badgeRepetitionText = new BadgeRepetitionText();
			GameObject val = new GameObject("RepetitionText");
			TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val2).font = LoadFont();
			((TMP_Text)val2).text = "";
			((TMP_Text)val2).fontSizeMax = 40f;
			((TMP_Text)val2).fontSizeMin = 18f;
			((TMP_Text)val2).horizontalAlignment = (HorizontalAlignmentOptions)4;
			badgeRepetitionText.gameObject = val;
			badgeRepetitionText.textComponent = val2;
			return badgeRepetitionText;
		}

		private static TMP_FontAsset LoadFont()
		{
			if ((Object)(object)fontAsset != (Object)null)
			{
				return fontAsset;
			}
			TMP_FontAsset val = ((IEnumerable<TMP_FontAsset>)Resources.FindObjectsOfTypeAll<TMP_FontAsset>()).FirstOrDefault((Func<TMP_FontAsset, bool>)((TMP_FontAsset asset) => ((Object)asset).name == "DarumaDropOne-Regular SDF"));
			if ((Object)(object)val == (Object)null)
			{
				Plugin.Log.LogDebug((object)"Unable to load DarumaDropOne-Regular SDF! Falling back to default font.");
				val = Resources.GetBuiltinResource<TMP_FontAsset>("LiberationSans SDF.asset");
			}
			fontAsset = val;
			return fontAsset;
		}

		public void UpdateCount(int newCount)
		{
			if (newCount < 2)
			{
				((TMP_Text)textComponent).text = "";
			}
			if (newCount > 99)
			{
				newCount = 99;
			}
			((TMP_Text)textComponent).text = $"x{newCount}";
		}
	}
}
namespace ScoutBadger.Saves
{
	[Serializable]
	public class BadgeEntry
	{
		public ACHIEVEMENTTYPE LinkedAchievement;

		public int ReceivedAmount;

		public DateTime FirstAcquiredAt;

		public DateTime LastAcquiredAt;
	}
	[Serializable]
	public class BadgeSaveData
	{
		public int version = 1;

		public List<BadgeEntry> entries = new List<BadgeEntry>();
	}
	internal class SaveManager
	{
		private BadgeSaveData? saveData;

		private string? filepath;

		public SaveManager(string filepath)
		{
			SetSavePath(filepath);
		}

		public void SetSavePath(string path)
		{
			if (string.IsNullOrEmpty(path))
			{
				Plugin.Log.LogWarning((object)"Provided save path is null or empty");
			}
			filepath = path;
		}

		public void Load()
		{
			if (string.IsNullOrEmpty(filepath))
			{
				throw new ArgumentException("Save path is not set. Call SetSavePath() first.");
			}
			if (!File.Exists(filepath))
			{
				saveData = new BadgeSaveData();
				return;
			}
			BadgeSaveData badgeSaveData = JsonConvert.DeserializeObject<BadgeSaveData>(File.ReadAllText(filepath));
			if (badgeSaveData == null)
			{
				Plugin.Log.LogWarning((object)"Unable to load badge save data. Falling back to default info.");
				saveData = new BadgeSaveData();
			}
			else
			{
				saveData = badgeSaveData;
			}
		}

		public void Save()
		{
			if (string.IsNullOrEmpty(filepath))
			{
				throw new ArgumentException("Save path is not set. Call SetSavePath() first.");
			}
			if (saveData == null)
			{
				Plugin.Log.LogWarning((object)"Ignoring attempt to save uninitialized data");
				return;
			}
			string contents = JsonConvert.SerializeObject((object)saveData, (Formatting)0);
			Directory.CreateDirectory(Path.GetDirectoryName(filepath));
			File.WriteAllText(filepath, contents);
		}

		public void IncrementBadgeRepetition(ACHIEVEMENTTYPE type)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if (saveData == null)
			{
				throw new InvalidOperationException("Save data is not initialized. Call Load() first.");
			}
			if (!TryGetBadge(type, out BadgeEntry badgeEntry))
			{
				badgeEntry = new BadgeEntry
				{
					LinkedAchievement = type,
					ReceivedAmount = 0
				};
				saveData.entries.Add(badgeEntry);
			}
			DateTime now = DateTime.Now;
			if (badgeEntry.ReceivedAmount == 0)
			{
				badgeEntry.FirstAcquiredAt = now;
			}
			badgeEntry.LastAcquiredAt = now;
			badgeEntry.ReceivedAmount++;
		}

		public bool TryGetBadge(ACHIEVEMENTTYPE type, out BadgeEntry badgeEntry)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			badgeEntry = GetBadge(type);
			if (badgeEntry == null)
			{
				return false;
			}
			return true;
		}

		public BadgeEntry? GetBadge(ACHIEVEMENTTYPE type)
		{
			//IL_0007: 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)
			if (saveData == null)
			{
				throw new InvalidOperationException("Save data is not initialized. Call Load() first.");
			}
			return saveData.entries.Find((BadgeEntry entry) => entry.LinkedAchievement == type);
		}
	}
}
namespace ScoutBadger.Patches
{
	internal class AchievementContext
	{
		private static AchievementContext _instance = null;

		private static readonly object _lock = new object();

		internal List<ACHIEVEMENTTYPE> repeatedAchievements = new List<ACHIEVEMENTTYPE>();

		public static AchievementContext Instance
		{
			get
			{
				if (_instance == null)
				{
					lock (_lock)
					{
						_instance = new AchievementContext();
					}
				}
				return _instance;
			}
		}
	}
	internal class AchievementManagerPatch
	{
		[HarmonyPatch(typeof(AchievementManager), "ThrowAchievement")]
		[HarmonyPostfix]
		private static void AddToEarnedAchievements(AchievementManager __instance, ACHIEVEMENTTYPE type)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (!__instance.runBasedValueData.achievementsEarnedThisRun.Contains(type))
			{
				__instance.runBasedValueData.achievementsEarnedThisRun.Add(type);
			}
		}

		[HarmonyPatch(typeof(AchievementManager), "ThrowAchievement")]
		[HarmonyPrefix]
		private static void AddRepeatedAchievements(AchievementManager __instance, ACHIEVEMENTTYPE type)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: 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)
			if (__instance.runBasedValueData.steamAchievementsPreviouslyUnlocked.Contains(type) && !AchievementContext.Instance.repeatedAchievements.Contains(type))
			{
				AchievementContext.Instance.repeatedAchievements.Add(type);
				Plugin.SaveManager.IncrementBadgeRepetition(type);
			}
		}
	}
	internal class BadgeUIPatch
	{
		[HarmonyPatch(typeof(BadgeUI), "Init")]
		[HarmonyPostfix]
		private static void CreateRepetitionText(BadgeUI __instance)
		{
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)((Component)__instance).transform.Find("RepetitionText")) && !(((Object)((Component)__instance).transform.parent).name == "Grid") && !((Object)(object)__instance.data == (Object)null))
			{
				BadgeRepetitionText badgeRepetitionText = BadgeRepetitionText.CreateTextObject();
				badgeRepetitionText.gameObject.transform.SetParent(((Component)__instance).gameObject.transform, false);
				RectTransform component = badgeRepetitionText.gameObject.GetComponent<RectTransform>();
				if (Object.op_Implicit((Object)(object)component))
				{
					component.anchorMin = new Vector2(0f, 0.5f);
					component.anchorMax = new Vector2(1f, 0.5f);
					component.anchoredPosition = new Vector2(0f, -15f);
					component.pivot = new Vector2(0.5f, 0.5f);
					component.sizeDelta = new Vector2(0f, 50f);
				}
				BadgeEntry badge = Plugin.SaveManager.GetBadge(__instance.data.linkedAchievement);
				if (badge != null)
				{
					badgeRepetitionText.UpdateCount(badge.ReceivedAmount);
				}
			}
		}
	}
	internal class EndScreenPatch
	{
		[HarmonyPatch]
		public static class BadgeRoutinePatch
		{
			private const int crownCheckLength = 10;

			private const int crownCheckNextIterationLabelOffset = 4;

			private const int illegalIndex = -1;

			private static MethodBase TargetMethod()
			{
				Type type = typeof(EndScreen).GetNestedTypes(BindingFlags.Public | BindingFlags.NonPublic).FirstOrDefault((Type t) => t.Name.Contains("<BadgeRoutine>"));
				return AccessTools.Method(type, "MoveNext", (Type[])null, (Type[])null);
			}

			private static IEnumerable<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions, ILGenerator il)
			{
				int num = -1;
				int num2 = -1;
				List<CodeInstruction> list = new List<CodeInstruction>(instructions);
				MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(Singleton<Customization>), "Instance");
				for (int i = 0; i < list.Count - 4; i++)
				{
					if (list[i].opcode == OpCodes.Call && (MethodInfo)list[i].operand == methodInfo && list[i + 1].opcode == OpCodes.Ldarg_0 && list[i + 4].opcode == OpCodes.Ldfld && list[i + 4].operand != null && num == -1)
					{
						num = i;
					}
					if (IsCrownCheck(list, i) && num2 == -1)
					{
						num2 = i;
					}
				}
				if (num == -1)
				{
					Plugin.Log.LogError((object)"[Transpiler] Unable to find Cosmetic loading instructions");
					return instructions;
				}
				if (num2 == -1)
				{
					Plugin.Log.LogError((object)"[Transpiler] Unable to find unlock crown check instructions");
					return instructions;
				}
				List<CodeInstruction> list2 = null;
				try
				{
					list2 = new List<CodeInstruction>(GetLoadBadgeDataSequence(list));
				}
				catch (InvalidOperationException ex)
				{
					Plugin.Log.LogError((object)("[Transpiler] Loading Badge Data sequence: " + ex.Message));
					return instructions;
				}
				Label label = il.DefineLabel();
				try
				{
					CodeInstruction val = FindEndOfCosmeticLoop(list);
					val.labels.Add(label);
				}
				catch (InvalidOperationException ex2)
				{
					Plugin.Log.LogError((object)("[Transpiler] Looking for end of cosmetic routine: " + ex2.Message));
					return instructions;
				}
				List<CodeInstruction> collection = new List<CodeInstruction>(CreateIsRepeatedCheck(list2, label));
				List<CodeInstruction> list3 = null;
				try
				{
					list3 = new List<CodeInstruction>(GetCrownCheckLoadCurrentAchievementSequence(list, num2 + 4));
				}
				catch (InvalidOperationException ex3)
				{
					Plugin.Log.LogError((object)("[Transpiler] Loading Crown Check sequence: " + ex3.Message));
					return instructions;
				}
				Label escapeLabel = (Label)list[num2 + 4].operand;
				List<CodeInstruction> list4 = new List<CodeInstruction>(CreateAdditionalRepeatedCrownCheck(list3, escapeLabel));
				list.InsertRange(num2 + 10, list4);
				list.InsertRange(num + list4.Count, collection);
				return list;
			}

			private static CodeInstruction FindEndOfCosmeticLoop(List<CodeInstruction> instructions, int startIdx = 0)
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(List<CustomizationOption>).GetNestedType("Enumerator"), "MoveNext", (Type[])null, (Type[])null);
				for (int i = startIdx; i < instructions.Count - 6; i++)
				{
					if (instructions[i].opcode == OpCodes.Ldarg_0 && instructions[i + 2].opcode == OpCodes.Call && instructions[i + 3].opcode == OpCodes.Brtrue && instructions[i + 4].opcode == OpCodes.Ldarg_0 && instructions[i + 6].opcode == OpCodes.Ldarg_0)
					{
						return instructions[i + 6];
					}
				}
				throw new InvalidOperationException("Unable to find end of the cosmetics loop");
			}

			private static bool IsCrownCheck(List<CodeInstruction> instructions, int index = 0)
			{
				MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(List<ACHIEVEMENTTYPE>), "Item");
				if (index >= 0 && index + 2 < instructions.Count && instructions[index].opcode == OpCodes.Ldloc_3 && instructions[index + 1].opcode == OpCodes.Ldloc_S && instructions[index + 2].opcode == OpCodes.Callvirt)
				{
					return (MethodInfo)instructions[index + 2].operand == methodInfo;
				}
				return false;
			}

			private static IEnumerable<CodeInstruction> GetLoadBadgeDataSequence(List<CodeInstruction> instructions, int startIdx = 0)
			{
				MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(List<BadgeData>), "Item");
				for (int i = startIdx; i < instructions.Count - 5; i++)
				{
					if (instructions[i].opcode == OpCodes.Ldarg_0 && instructions[i + 2].opcode == OpCodes.Ldarg_0 && instructions[i + 4].opcode == OpCodes.Callvirt && (MethodInfo)instructions[i + 4].operand == methodInfo)
					{
						return instructions.GetRange(i, 5);
					}
				}
				throw new InvalidOperationException("Unable to find BadgeData loader");
			}

			private static IEnumerable<CodeInstruction> GetCrownCheckLoadCurrentAchievementSequence(List<CodeInstruction> instructions, int startIdx)
			{
				for (int i = startIdx; i < instructions.Count - 2; i++)
				{
					if (IsCrownCheck(instructions, i))
					{
						return instructions.GetRange(i, 3);
					}
				}
				throw new InvalidOperationException("Unable to find CurrentAchievement loader");
			}

			private static IEnumerable<CodeInstruction> CreateAdditionalRepeatedCrownCheck(IEnumerable<CodeInstruction> currentAchievement, Label escapeLabel)
			{
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_0067: Expected O, but got Unknown
				//IL_006f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0075: Expected O, but got Unknown
				//IL_0089: Unknown result type (might be due to invalid IL or missing references)
				//IL_008f: Expected O, but got Unknown
				//IL_009c: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a2: Expected O, but got Unknown
				MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(AchievementContext), "Instance");
				FieldInfo fieldInfo = AccessTools.Field(typeof(AchievementContext), "repeatedAchievements");
				MethodInfo methodInfo2 = AccessTools.Method(typeof(List<ACHIEVEMENTTYPE>), "Contains", new Type[1] { typeof(ACHIEVEMENTTYPE) }, (Type[])null);
				return ((IEnumerable<CodeInstruction>)(object)new CodeInstruction[2]
				{
					new CodeInstruction(OpCodes.Call, (object)methodInfo),
					new CodeInstruction(OpCodes.Ldfld, (object)fieldInfo)
				}).Concat(currentAchievement).Concat((IEnumerable<CodeInstruction>)(object)new CodeInstruction[2]
				{
					new CodeInstruction(OpCodes.Callvirt, (object)methodInfo2),
					new CodeInstruction(OpCodes.Brtrue, (object)escapeLabel)
				});
			}

			private static IEnumerable<CodeInstruction> CreateIsRepeatedCheck(IEnumerable<CodeInstruction> badgeDataSeq, Label escapeLabel)
			{
				//IL_0077: Unknown result type (might be due to invalid IL or missing references)
				//IL_007d: Expected O, but got Unknown
				//IL_0085: Unknown result type (might be due to invalid IL or missing references)
				//IL_008b: Expected O, but got Unknown
				//IL_0098: Unknown result type (might be due to invalid IL or missing references)
				//IL_009e: Expected O, but got Unknown
				//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b7: Expected O, but got Unknown
				//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c5: Expected O, but got Unknown
				//IL_00de: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e4: Expected O, but got Unknown
				//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
				//IL_00f2: Expected O, but got Unknown
				//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
				//IL_0105: Expected O, but got Unknown
				MethodInfo methodInfo = AccessTools.PropertyGetter(typeof(AchievementContext), "Instance");
				FieldInfo fieldInfo = AccessTools.Field(typeof(AchievementContext), "repeatedAchievements");
				FieldInfo fieldInfo2 = AccessTools.Field(typeof(BadgeData), "linkedAchievement");
				MethodInfo methodInfo2 = AccessTools.Method(typeof(List<ACHIEVEMENTTYPE>), "Contains", new Type[1] { typeof(ACHIEVEMENTTYPE) }, (Type[])null);
				return badgeDataSeq.Concat((IEnumerable<CodeInstruction>)(object)new CodeInstruction[3]
				{
					new CodeInstruction(OpCodes.Ldnull, (object)null),
					new CodeInstruction(OpCodes.Ceq, (object)null),
					new CodeInstruction(OpCodes.Brtrue, (object)escapeLabel)
				}).Concat((IEnumerable<CodeInstruction>)(object)new CodeInstruction[2]
				{
					new CodeInstruction(OpCodes.Call, (object)methodInfo),
					new CodeInstruction(OpCodes.Ldfld, (object)fieldInfo)
				}).Concat(badgeDataSeq)
					.Concat((IEnumerable<CodeInstruction>)(object)new CodeInstruction[3]
					{
						new CodeInstruction(OpCodes.Ldfld, (object)fieldInfo2),
						new CodeInstruction(OpCodes.Callvirt, (object)methodInfo2),
						new CodeInstruction(OpCodes.Brtrue, (object)escapeLabel)
					});
			}
		}
	}
}
namespace ScoutBadger.Configuration
{
	internal static class SaveConfig
	{
		private static readonly string defaultSavefile = Path.Combine(Paths.ConfigPath, "ScoutBadger", "badges.json");

		private static ConfigEntry<string> _customSavefile = null;

		public static string SafeFile
		{
			get
			{
				if (_customSavefile == null)
				{
					throw new InvalidOperationException("SaveConfig is not bound to a config file");
				}
				string value = defaultSavefile;
				if (_customSavefile.Value != "")
				{
					value = _customSavefile.Value;
				}
				return value;
			}
		}

		public static void BindConfig(ConfigFile config)
		{
			_customSavefile = config.Bind<string>("SaveData", "CustomFilepath", "", "Optional. Overrides default save location.");
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}