Decompiled source of CiCisTrinketAndBindingFramework v2.1.4

plugins\TrinketAndBindingFramework\TrinketAndBindingFramework.dll

Decompiled 3 weeks ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;

[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("TrinketAndBindingFramework")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("TrinketAndBindingFramework")]
[assembly: AssemblyTitle("TrinketAndBindingFramework")]
[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 TrinketAndBindingFramework
{
	public static class CustomModeRegistry
	{
		public enum Difficulty
		{
			Easy,
			Medium,
			Hard,
			Extreme
		}

		public class Mode
		{
			public string Id;

			public string DisplayName;

			public string Description;

			public Difficulty Difficulty;

			public Action<bool> OnToggle;

			public List<string> ExclusiveSettingIds;

			public bool DisablesLeaderboards;

			public string HoverCreditText;

			internal GamemodeSetting RuntimeSetting;

			public string SourceMod;

			public string SourceModGuid;
		}

		internal static readonly Dictionary<string, Mode> _modes = new Dictionary<string, Mode>(StringComparer.Ordinal);

		internal static readonly List<(string[] ids, string display)> _combos = new List<(string[], string)>();

		internal static readonly Dictionary<string, string> _disabledLocks = new Dictionary<string, string>(StringComparer.Ordinal);

		internal static readonly List<(string a, string b)> _mutualLinks = new List<(string, string)>();

		internal static readonly HashSet<string> _injectedGamemodes = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		internal static readonly Dictionary<string, string> _gamemodeAliases = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

		internal static Color LinkColor = new Color(1f, 0.55f, 0.1f, 1f);

		public static IReadOnlyDictionary<string, Mode> All => _modes;

		public static void Register(string id, string displayName, string description, Difficulty difficulty, Action<bool> onToggle, string[] exclusiveSettingIds = null, bool disablesLeaderboards = true, string hoverCreditText = null)
		{
			if (string.IsNullOrEmpty(id))
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"[CustomModeRegistry] empty id, skipped");
				}
				return;
			}
			TrinketRegistry.DetectCallingMod(out var name, out var guid);
			_modes[id] = new Mode
			{
				Id = id,
				DisplayName = (displayName ?? id),
				Description = (description ?? ""),
				Difficulty = difficulty,
				OnToggle = onToggle,
				ExclusiveSettingIds = ((exclusiveSettingIds != null) ? new List<string>(exclusiveSettingIds) : new List<string>()),
				DisablesLeaderboards = disablesLeaderboards,
				HoverCreditText = hoverCreditText,
				SourceMod = name,
				SourceModGuid = guid
			};
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("[CustomModeRegistry] mode: " + id + ((name != null) ? (" (from " + name + ")") : "")));
			}
		}

		public static void RegisterCombo(string[] modeIds, string displayName)
		{
			if (modeIds != null && modeIds.Length >= 2 && !string.IsNullOrEmpty(displayName))
			{
				string[] array = (string[])modeIds.Clone();
				Array.Sort(array, (IComparer<string>?)StringComparer.Ordinal);
				_combos.Add((array, displayName));
			}
		}

		public static void RegisterDisabledLock(string modeId, string lockText = "WIP")
		{
			if (!string.IsNullOrEmpty(modeId))
			{
				_disabledLocks[modeId] = lockText ?? "WIP";
			}
		}

		public static void RegisterMutualLink(string idA, string idB)
		{
			if (!string.IsNullOrEmpty(idA) && !string.IsNullOrEmpty(idB))
			{
				_mutualLinks.Add((idA, idB));
			}
		}

		public static void InjectIntoGamemode(string gamemodeName)
		{
			if (!string.IsNullOrEmpty(gamemodeName))
			{
				_injectedGamemodes.Add(gamemodeName);
			}
		}

		public static void RegisterGamemodeAlias(string aliasGamemodeName, string sourceGamemodeName)
		{
			if (!string.IsNullOrEmpty(aliasGamemodeName) && !string.IsNullOrEmpty(sourceGamemodeName))
			{
				_gamemodeAliases[aliasGamemodeName] = sourceGamemodeName;
			}
		}

		public static bool IsActive(string id)
		{
			if (string.IsNullOrEmpty(id))
			{
				return false;
			}
			M_Gamemode currentGamemode = CL_GameManager.GetCurrentGamemode();
			if ((Object)(object)currentGamemode == (Object)null)
			{
				return false;
			}
			try
			{
				return currentGamemode.HasActiveSetting(id);
			}
			catch
			{
				return false;
			}
		}

		public static bool AnyActive()
		{
			M_Gamemode currentGamemode = CL_GameManager.GetCurrentGamemode();
			if ((Object)(object)currentGamemode == (Object)null)
			{
				return false;
			}
			foreach (string key in _modes.Keys)
			{
				try
				{
					if (currentGamemode.HasActiveSetting(key))
					{
						return true;
					}
				}
				catch
				{
				}
			}
			return false;
		}

		public static bool IsDisabled(string id)
		{
			if (!string.IsNullOrEmpty(id))
			{
				return _disabledLocks.ContainsKey(id);
			}
			return false;
		}

		public static string GetLockText(string id)
		{
			if (!_disabledLocks.TryGetValue(id ?? "", out var value))
			{
				return "WIP";
			}
			return value;
		}

		internal static bool ShouldShowLinkColor(string id)
		{
			if (IsDisabled(id))
			{
				return false;
			}
			foreach (var (id2, text) in _mutualLinks)
			{
				if (id == text && IsActive(id2) && !IsActive(text))
				{
					return true;
				}
			}
			return false;
		}

		internal static Color DifficultyColor(Difficulty d)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_006c: 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_007a: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			return (Color)(d switch
			{
				Difficulty.Easy => new Color(0f, 1f, 0f), 
				Difficulty.Medium => new Color(1f, 0.65f, 0f), 
				Difficulty.Hard => new Color(1f, 0f, 0f), 
				Difficulty.Extreme => new Color(0.7f, 0.12f, 0f), 
				_ => Color.white, 
			});
		}
	}
	internal static class CustomModePickerIntegration
	{
		private static ProgressionUnlock _alwaysUnlocked;

		private static bool _built;

		private static int _builtModeCount;

		internal static void EnsureBuilt()
		{
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			if (_built && _builtModeCount == CustomModeRegistry._modes.Count)
			{
				return;
			}
			if ((Object)(object)_alwaysUnlocked == (Object)null)
			{
				_alwaysUnlocked = ScriptableObject.CreateInstance<ProgressionUnlock>();
				((Object)_alwaysUnlocked).name = "CiCi_CustomMode_AlwaysUnlocked";
				_alwaysUnlocked.unlockRequirements = new List<UnlockRequirement>();
				_alwaysUnlocked.state = true;
				_alwaysUnlocked.unlockHint = "";
				_alwaysUnlocked.progressionString = "";
				Object.DontDestroyOnLoad((Object)(object)_alwaysUnlocked);
			}
			foreach (KeyValuePair<string, CustomModeRegistry.Mode> mode in CustomModeRegistry._modes)
			{
				CustomModeRegistry.Mode value = mode.Value;
				if (!((Object)(object)value.RuntimeSetting != (Object)null))
				{
					GamemodeSetting val = ScriptableObject.CreateInstance<GamemodeSetting>();
					((Object)val).name = "GamemodeSetting_CustomMode_" + value.Id;
					val.id = value.Id;
					val.title = value.DisplayName;
					val.description = value.Description;
					val.color = CustomModeRegistry.DifficultyColor(value.Difficulty);
					val.unlock = _alwaysUnlocked;
					val.exclusiveSettings = new List<string>(value.ExclusiveSettingIds ?? new List<string>());
					val.nameAppend = "";
					val.leaderboardAppendID = "";
					Object.DontDestroyOnLoad((Object)(object)val);
					value.RuntimeSetting = val;
				}
			}
			_built = true;
			_builtModeCount = CustomModeRegistry._modes.Count;
		}

		internal static void InjectInto(M_Gamemode gm)
		{
			if ((Object)(object)gm == (Object)null)
			{
				return;
			}
			EnsureBuilt();
			string item = gm.gamemodeName ?? "";
			if (!CustomModeRegistry._injectedGamemodes.Contains(item))
			{
				return;
			}
			if (gm.gamemodeSettings == null)
			{
				gm.gamemodeSettings = new List<GamemodeSetting>();
			}
			foreach (CustomModeRegistry.Mode value in CustomModeRegistry._modes.Values)
			{
				if (!((Object)(object)value.RuntimeSetting == (Object)null) && !gm.gamemodeSettings.Contains(value.RuntimeSetting))
				{
					gm.gamemodeSettings.Add(value.RuntimeSetting);
				}
			}
		}
	}
	[HarmonyPatch(typeof(UI_GamemodeSetting), "ToggleSetting")]
	internal static class CustomModeToggleSyncPatch
	{
		[HarmonyPostfix]
		private static void Postfix(UI_GamemodeSetting __instance, bool b)
		{
			GamemodeSetting val = __instance?.gamemodeSetting;
			if ((Object)(object)val == (Object)null || string.IsNullOrEmpty(val.id) || !CustomModeRegistry._modes.TryGetValue(val.id, out var value))
			{
				return;
			}
			if (CustomModeRegistry.IsDisabled(val.id))
			{
				try
				{
					value.OnToggle?.Invoke(obj: false);
				}
				catch
				{
				}
				if ((Object)(object)__instance.toggle != (Object)null && __instance.toggle.isOn)
				{
					try
					{
						__instance.toggle.SetIsOnWithoutNotify(false);
					}
					catch
					{
						try
						{
							__instance.toggle.isOn = false;
						}
						catch
						{
						}
					}
				}
				UI_GamemodeScreen_Panel panel = GamemodeSettingUnlockBypass.GetPanel(__instance);
				M_Gamemode val2 = ((panel != null) ? panel.GetGamemode() : null);
				object obj4;
				if (!((Object)(object)val2 != (Object)null))
				{
					obj4 = null;
				}
				else
				{
					SaveData saveData = StatManager.saveData;
					obj4 = ((saveData != null) ? saveData.GetGameMode(val2.gamemodeName) : null);
				}
				((GameModeData)(obj4?)).activeSettings?.Remove(val.id);
				return;
			}
			try
			{
				value.OnToggle?.Invoke(b);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[CustomMode] Toggle " + val.id + " failed: " + ex.Message));
				}
			}
			UI_GamemodeScreen_Panel panel2 = GamemodeSettingUnlockBypass.GetPanel(__instance);
			M_Gamemode val3 = ((panel2 != null) ? panel2.GetGamemode() : null);
			if ((Object)(object)val3 != (Object)null)
			{
				LeaderboardGate.Apply(LeaderboardGate.ShouldDisableForGamemode(val3));
			}
			LeaderboardWarning.RefreshAll();
			CustomModeLinks.RefreshLinkedSetting(__instance);
			UI_GamemodeOptionsText[] array = Object.FindObjectsOfType<UI_GamemodeOptionsText>();
			foreach (UI_GamemodeOptionsText val4 in array)
			{
				if ((Object)(object)val4 != (Object)null)
				{
					try
					{
						val4.Refresh();
					}
					catch
					{
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(UI_GamemodeSetting), "ToggleSetting")]
	internal static class CustomModeDisabledToggleBlockPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(UI_GamemodeSetting __instance)
		{
			return !CustomModeRegistry.IsDisabled(__instance?.gamemodeSetting?.id);
		}
	}
	[HarmonyPatch(typeof(M_Gamemode), "StartFreshGamemode")]
	internal static class CustomModeStartSyncPatch
	{
		[HarmonyPostfix]
		private static void Postfix(M_Gamemode __instance)
		{
			if ((Object)(object)__instance == (Object)null || CustomModeRegistry._modes.Count == 0)
			{
				return;
			}
			string text = __instance.gamemodeName ?? "";
			string text2 = text;
			if (CustomModeRegistry._gamemodeAliases.TryGetValue(text, out var value))
			{
				text2 = value;
			}
			if (!CustomModeRegistry._injectedGamemodes.Contains(text2))
			{
				foreach (CustomModeRegistry.Mode value2 in CustomModeRegistry._modes.Values)
				{
					try
					{
						value2.OnToggle?.Invoke(obj: false);
					}
					catch
					{
					}
				}
				return;
			}
			M_Gamemode val = ((text2 == text) ? __instance : FindGamemodeByName(text2));
			foreach (KeyValuePair<string, CustomModeRegistry.Mode> mode in CustomModeRegistry._modes)
			{
				if (CustomModeRegistry.IsDisabled(mode.Key))
				{
					try
					{
						mode.Value.OnToggle?.Invoke(obj: false);
					}
					catch
					{
					}
					continue;
				}
				bool obj3 = false;
				try
				{
					obj3 = val != null && val.HasActiveSetting(mode.Key);
				}
				catch
				{
				}
				try
				{
					mode.Value.OnToggle?.Invoke(obj3);
				}
				catch (Exception ex)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("[CustomMode] Start sync " + mode.Key + " failed: " + ex.Message));
					}
				}
			}
		}

		private static M_Gamemode FindGamemodeByName(string name)
		{
			M_Gamemode[] array = Resources.FindObjectsOfTypeAll<M_Gamemode>();
			if (array == null)
			{
				return null;
			}
			foreach (M_Gamemode val in array)
			{
				if ((Object)(object)val != (Object)null && string.Equals(val.gamemodeName, name, StringComparison.OrdinalIgnoreCase))
				{
					return val;
				}
			}
			return null;
		}
	}
	[HarmonyPatch(typeof(UI_GamemodeScreen), "Initialize")]
	internal static class CustomModeSaveDataCleanupPatch
	{
		[HarmonyPostfix]
		private static void Postfix(M_Gamemode mode)
		{
			if ((Object)(object)mode == (Object)null || CustomModeRegistry._disabledLocks.Count == 0)
			{
				return;
			}
			SaveData saveData = StatManager.saveData;
			List<string> list = ((saveData != null) ? saveData.GetGameMode(mode.gamemodeName) : null)?.activeSettings;
			if (list == null)
			{
				return;
			}
			for (int num = list.Count - 1; num >= 0; num--)
			{
				if (CustomModeRegistry.IsDisabled(list[num]))
				{
					list.RemoveAt(num);
				}
			}
			foreach (string key in CustomModeRegistry._disabledLocks.Keys)
			{
				if (CustomModeRegistry._modes.TryGetValue(key, out var value))
				{
					try
					{
						value.OnToggle?.Invoke(obj: false);
					}
					catch
					{
					}
				}
			}
		}
	}
	internal static class CustomModeLinks
	{
		private static readonly MethodInfo _updateColorMethod = AccessTools.Method(typeof(UI_GamemodeSetting), "UpdateColor", (Type[])null, (Type[])null);

		public static void RefreshLinkedSetting(UI_GamemodeSetting source)
		{
			string text = source?.gamemodeSetting?.id;
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			HashSet<string> hashSet = new HashSet<string>(StringComparer.Ordinal);
			foreach (var (text2, text3) in CustomModeRegistry._mutualLinks)
			{
				if (text2 == text)
				{
					hashSet.Add(text3);
				}
				if (text3 == text)
				{
					hashSet.Add(text2);
				}
			}
			if (hashSet.Count == 0)
			{
				return;
			}
			UI_GamemodeScreen_Panel panel = GamemodeSettingUnlockBypass.GetPanel(source);
			if ((Object)(object)panel == (Object)null)
			{
				return;
			}
			UI_GamemodeSetting[] componentsInChildren = ((Component)panel).GetComponentsInChildren<UI_GamemodeSetting>(true);
			foreach (UI_GamemodeSetting val in componentsInChildren)
			{
				string text4 = val?.gamemodeSetting?.id;
				if (text4 == null || !hashSet.Contains(text4))
				{
					continue;
				}
				try
				{
					_updateColorMethod?.Invoke(val, null);
				}
				catch (Exception ex)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("[CustomModeLinks] Refresh " + text4 + " failed: " + ex.Message));
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(UI_GamemodeSetting), "UpdateColor")]
	[HarmonyPriority(200)]
	internal static class CustomModeLinkColorPatch
	{
		[HarmonyPostfix]
		private static void Postfix(UI_GamemodeSetting __instance)
		{
			//IL_0020: 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)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: 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)
			if (!CustomModeRegistry.ShouldShowLinkColor(__instance?.gamemodeSetting?.id))
			{
				return;
			}
			Color linkColor = CustomModeRegistry.LinkColor;
			if ((Object)(object)__instance.outline != (Object)null)
			{
				((Graphic)__instance.outline).color = linkColor;
			}
			if ((Object)(object)__instance.titleText != (Object)null)
			{
				((Graphic)__instance.titleText).color = linkColor;
			}
			if ((Object)(object)__instance.descriptionText != (Object)null)
			{
				((Graphic)__instance.descriptionText).color = linkColor;
			}
			if ((Object)(object)__instance.toggle != (Object)null)
			{
				if ((Object)(object)((Selectable)__instance.toggle).targetGraphic != (Object)null)
				{
					((Selectable)__instance.toggle).targetGraphic.color = linkColor;
				}
				if ((Object)(object)__instance.toggle.graphic != (Object)null)
				{
					__instance.toggle.graphic.color = linkColor;
				}
			}
		}
	}
	[HarmonyPatch(typeof(UI_GamemodeSetting), "UpdateColor")]
	[HarmonyPriority(200)]
	internal static class CustomModeDisabledLockColorPatch
	{
		[HarmonyPostfix]
		private static void Postfix(UI_GamemodeSetting __instance)
		{
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: 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)
			string id = __instance?.gamemodeSetting?.id;
			if (!CustomModeRegistry.IsDisabled(id))
			{
				return;
			}
			if ((Object)(object)__instance.toggle != (Object)null)
			{
				((Selectable)__instance.toggle).interactable = false;
			}
			if ((Object)(object)__instance.lockObject != (Object)null)
			{
				__instance.lockObject.SetActive(true);
			}
			if ((Object)(object)__instance.descriptionText != (Object)null)
			{
				__instance.descriptionText.text = CustomModeRegistry.GetLockText(id);
			}
			Color grey = Color.grey;
			if ((Object)(object)__instance.outline != (Object)null)
			{
				((Graphic)__instance.outline).color = grey;
			}
			if ((Object)(object)__instance.titleText != (Object)null)
			{
				((Graphic)__instance.titleText).color = grey;
			}
			if ((Object)(object)__instance.descriptionText != (Object)null)
			{
				((Graphic)__instance.descriptionText).color = grey;
			}
			if ((Object)(object)__instance.unlockHint != (Object)null)
			{
				((Graphic)__instance.unlockHint).color = grey;
			}
			if ((Object)(object)__instance.toggle != (Object)null)
			{
				if ((Object)(object)((Selectable)__instance.toggle).targetGraphic != (Object)null)
				{
					((Selectable)__instance.toggle).targetGraphic.color = grey;
				}
				if ((Object)(object)__instance.toggle.graphic != (Object)null)
				{
					__instance.toggle.graphic.color = grey;
				}
			}
		}
	}
	[HarmonyPatch(typeof(GamemodeSettingUnlockBypass), "ForceUnlocked")]
	internal static class CustomModeSkipForceUnlockPatch
	{
		[HarmonyPrefix]
		private static bool Prefix(UI_GamemodeSetting inst)
		{
			return !CustomModeRegistry.IsDisabled(inst?.gamemodeSetting?.id);
		}
	}
	internal static class CustomModeCredit
	{
		private const string ObjectName = "CiCi_CustomModeCreditText";

		private static readonly Dictionary<UI_GamemodeScreen_Panel, TextMeshProUGUI> _byPanel = new Dictionary<UI_GamemodeScreen_Panel, TextMeshProUGUI>();

		public static void EnsureForPanel(UI_GamemodeScreen_Panel panel)
		{
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: 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_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: 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)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)panel == (Object)null || (_byPanel.TryGetValue(panel, out var value) && (Object)(object)value != (Object)null))
			{
				return;
			}
			Transform settingRoot = panel.settingRoot;
			if ((Object)(object)settingRoot == (Object)null)
			{
				return;
			}
			Transform parent = settingRoot.parent;
			if ((Object)(object)parent != (Object)null && ((Object)parent).name == "CiCi_SettingsScrollViewport")
			{
				parent = parent.parent;
			}
			RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			if (!((Object)(object)val == (Object)null))
			{
				TMP_FontAsset val2 = null;
				TextMeshProUGUI componentInChildren = ((Component)val).GetComponentInChildren<TextMeshProUGUI>(true);
				if ((Object)(object)componentInChildren != (Object)null)
				{
					val2 = ((TMP_Text)componentInChildren).font;
				}
				GameObject val3 = new GameObject("CiCi_CustomModeCreditText", new Type[1] { typeof(RectTransform) });
				RectTransform val4 = (RectTransform)val3.transform;
				((Transform)val4).SetParent((Transform)(object)val, false);
				val4.anchorMin = new Vector2(0f, 0f);
				val4.anchorMax = new Vector2(1f, 0f);
				val4.pivot = new Vector2(0.5f, 0f);
				val4.anchoredPosition = new Vector2(0f, 4f);
				val4.sizeDelta = new Vector2(-20f, 22f);
				TextMeshProUGUI val5 = val3.AddComponent<TextMeshProUGUI>();
				((TMP_Text)val5).text = "";
				((TMP_Text)val5).fontSize = 14f;
				((TMP_Text)val5).alignment = (TextAlignmentOptions)514;
				((Graphic)val5).color = new Color(0.72f, 0.72f, 0.72f, 0.95f);
				((TMP_Text)val5).fontStyle = (FontStyles)2;
				((Graphic)val5).raycastTarget = false;
				if ((Object)(object)val2 != (Object)null)
				{
					((TMP_Text)val5).font = val2;
				}
				val3.SetActive(false);
				_byPanel[panel] = val5;
			}
		}

		public static void Show(UI_GamemodeScreen_Panel panel, string text)
		{
			if (!((Object)(object)panel == (Object)null) && !string.IsNullOrEmpty(text) && _byPanel.TryGetValue(panel, out var value) && !((Object)(object)value == (Object)null))
			{
				((TMP_Text)value).text = text;
				if (!((Component)value).gameObject.activeSelf)
				{
					((Component)value).gameObject.SetActive(true);
				}
			}
		}

		public static void Hide(UI_GamemodeScreen_Panel panel)
		{
			if (!((Object)(object)panel == (Object)null) && _byPanel.TryGetValue(panel, out var value) && !((Object)(object)value == (Object)null) && ((Component)value).gameObject.activeSelf)
			{
				((Component)value).gameObject.SetActive(false);
			}
		}

		public static string GetCreditFor(string modeId)
		{
			if (!CustomModeRegistry._modes.TryGetValue(modeId ?? "", out var value))
			{
				return null;
			}
			return value.HoverCreditText;
		}
	}
	public class CustomModeCreditHover : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler
	{
		public UI_GamemodeSetting setting;

		public static void AttachTo(UI_GamemodeSetting setting)
		{
			if (!((Object)(object)setting == (Object)null) && !((Object)(object)((Component)setting).gameObject == (Object)null))
			{
				CustomModeCreditHover component = ((Component)setting).GetComponent<CustomModeCreditHover>();
				if ((Object)(object)component != (Object)null)
				{
					component.setting = setting;
				}
				else
				{
					((Component)setting).gameObject.AddComponent<CustomModeCreditHover>().setting = setting;
				}
			}
		}

		public void OnPointerEnter(PointerEventData _)
		{
			if ((Object)(object)setting == (Object)null)
			{
				return;
			}
			string creditFor = CustomModeCredit.GetCreditFor(setting.gamemodeSetting?.id);
			if (!string.IsNullOrEmpty(creditFor))
			{
				UI_GamemodeScreen_Panel panel = GamemodeSettingUnlockBypass.GetPanel(setting);
				if ((Object)(object)panel != (Object)null)
				{
					CustomModeCredit.Show(panel, creditFor);
				}
			}
		}

		public void OnPointerExit(PointerEventData _)
		{
			if (!((Object)(object)setting == (Object)null))
			{
				UI_GamemodeScreen_Panel panel = GamemodeSettingUnlockBypass.GetPanel(setting);
				if ((Object)(object)panel != (Object)null)
				{
					CustomModeCredit.Hide(panel);
				}
			}
		}
	}
	[HarmonyPatch(typeof(UI_GamemodeOptionsText), "Refresh")]
	internal static class CustomModeComboDisplayPatch
	{
		[HarmonyPostfix]
		private static void Postfix(UI_GamemodeOptionsText __instance)
		{
			if ((Object)(object)__instance == (Object)null || CustomModeRegistry._combos.Count == 0)
			{
				return;
			}
			TMP_Text component = ((Component)__instance).GetComponent<TMP_Text>();
			if ((Object)(object)component == (Object)null)
			{
				return;
			}
			M_Gamemode currentGamemode = CL_GameManager.GetCurrentGamemode();
			if ((Object)(object)currentGamemode == (Object)null)
			{
				return;
			}
			List<string> list = new List<string>();
			foreach (string key in CustomModeRegistry._modes.Keys)
			{
				try
				{
					if (currentGamemode.HasActiveSetting(key))
					{
						list.Add(key);
					}
				}
				catch
				{
				}
			}
			if (list.Count < 2)
			{
				return;
			}
			list.Sort(StringComparer.Ordinal);
			for (int i = 0; i < CustomModeRegistry._combos.Count; i++)
			{
				var (array, text) = CustomModeRegistry._combos[i];
				if (array.Length != list.Count)
				{
					continue;
				}
				bool flag = true;
				for (int j = 0; j < array.Length; j++)
				{
					if (array[j] != list[j])
					{
						flag = false;
						break;
					}
				}
				if (flag)
				{
					component.text = text;
					break;
				}
			}
		}
	}
	[BepInPlugin("com.cicismods.trinketandbindingframework", "CiCi's Trinket & Binding Framework", "2.1.4")]
	public class Plugin : BaseUnityPlugin
	{
		public const string GUID = "com.cicismods.trinketandbindingframework";

		public const string NAME = "CiCi's Trinket & Binding Framework";

		public const string VERSION = "2.1.4";

		public static ManualLogSource Log;

		private void Awake()
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			Harmony val = new Harmony("com.cicismods.trinketandbindingframework");
			Type[] types = Assembly.GetExecutingAssembly().GetTypes();
			foreach (Type type in types)
			{
				try
				{
					val.CreateClassProcessor(type).Patch();
				}
				catch (Exception ex)
				{
					Log.LogError((object)("[Harmony] patch " + type.FullName + " failed: " + ex.Message));
				}
			}
			Log.LogInfo((object)"CiCi's Trinket & Binding Framework 2.1.4 loaded");
		}
	}
	public static class TrinketRegistry
	{
		public enum Bucket
		{
			Vanilla,
			Parasite,
			Chimney
		}

		public enum Category
		{
			Consumable,
			Tool,
			Other,
			Artifact,
			Perk
		}

		internal class Entry
		{
			public string id;

			public string title;

			public string description;

			public string flavorText;

			public bool isBinding;

			public int cost;

			public float scoreMultiplierBonus;

			public float scoreBonus;

			public Sprite icon;

			public Func<List<Item_Object>> itemsToGrantFactory;

			public Func<List<Perk>> perksToGrantFactory;

			public int pouchesToGrant;

			public Trinket runtime;

			public string idLower;

			public string runtimeNameLower;

			public int stackCount = 1;

			public int maxStacks = 1;

			public string titleColor;

			public Bucket bucket;

			public Category category = Category.Other;

			public int tier;

			public bool isFrameworkRegistered;

			public bool pinToVanilla;

			public bool isVanillaContent;

			public string sourceMod;

			public string sourceModGuid;

			public bool disablesLeaderboards = true;
		}

		internal static readonly Dictionary<string, Entry> _registry = new Dictionary<string, Entry>();

		internal static readonly Dictionary<Trinket, Entry> _byRuntime = new Dictionary<Trinket, Entry>();

		internal static readonly Dictionary<string, List<string>> _mutexGroups = new Dictionary<string, List<string>>();

		internal static Bucket BucketFromColor(string colorHex)
		{
			if (string.IsNullOrEmpty(colorHex))
			{
				return Bucket.Vanilla;
			}
			string text = colorHex.TrimStart('#').ToUpperInvariant();
			if (text == "18420F")
			{
				return Bucket.Parasite;
			}
			if (text == "8DDDF5")
			{
				return Bucket.Chimney;
			}
			return Bucket.Vanilla;
		}

		internal static bool IsGrey(string colorHex)
		{
			if (string.IsNullOrEmpty(colorHex))
			{
				return true;
			}
			return colorHex.TrimStart('#').ToUpperInvariant() == "D3D3D3";
		}

		internal static Entry FindEntryForTrinket(Trinket t)
		{
			if ((Object)(object)t == (Object)null)
			{
				return null;
			}
			if (!_byRuntime.TryGetValue(t, out var value))
			{
				return null;
			}
			return value;
		}

		internal static void RegisterRuntime(Trinket runtime, Entry entry)
		{
			if (!((Object)(object)runtime == (Object)null) && entry != null)
			{
				_byRuntime[runtime] = entry;
				entry.runtimeNameLower = ((Object)runtime).name?.ToLowerInvariant() ?? "";
			}
		}

		public static void RegisterMutexGroup(string groupId, params string[] entryIds)
		{
			if (!string.IsNullOrEmpty(groupId) && entryIds != null)
			{
				List<string> value = new List<string>(entryIds);
				_mutexGroups[groupId] = value;
			}
		}

		public static Trinket GetRuntimeTrinket(string id)
		{
			if (string.IsNullOrEmpty(id))
			{
				return null;
			}
			if (!_registry.TryGetValue(id, out var value))
			{
				return null;
			}
			return value.runtime;
		}

		public static void RegisterTrinket(string id, string title, string description, string flavorText = "", int cost = 1, float scoreMultiplierBonus = 0f, float scoreBonus = 0f, Sprite icon = null, Func<List<Item_Object>> itemsToGrantFactory = null, Func<List<Perk>> perksToGrantFactory = null, int pouchesToGrant = 0)
		{
			Register(id, title, description, flavorText, isBinding: false, cost, scoreMultiplierBonus, scoreBonus, icon, itemsToGrantFactory, perksToGrantFactory, pouchesToGrant);
		}

		public static void RegisterBinding(string id, string title, string description, string flavorText = "", int cost = 1, float scoreMultiplierBonus = 0f, float scoreBonus = 0f, Sprite icon = null, Func<List<Item_Object>> itemsToGrantFactory = null, Func<List<Perk>> perksToGrantFactory = null, int pouchesToGrant = 0)
		{
			Register(id, title, description, flavorText, isBinding: true, cost, scoreMultiplierBonus, scoreBonus, icon, itemsToGrantFactory, perksToGrantFactory, pouchesToGrant);
		}

		private static void Register(string id, string title, string description, string flavorText, bool isBinding, int cost, float scoreMultiplierBonus, float scoreBonus, Sprite icon, Func<List<Item_Object>> itemsToGrantFactory, Func<List<Perk>> perksToGrantFactory, int pouchesToGrant)
		{
			if (string.IsNullOrEmpty(id))
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"[Registry] empty id, skipped");
				}
				return;
			}
			_registry[id] = new Entry
			{
				id = id,
				idLower = id.ToLowerInvariant(),
				title = title,
				description = description,
				flavorText = (flavorText ?? ""),
				isBinding = isBinding,
				cost = cost,
				scoreMultiplierBonus = scoreMultiplierBonus,
				scoreBonus = scoreBonus,
				icon = icon,
				itemsToGrantFactory = itemsToGrantFactory,
				perksToGrantFactory = perksToGrantFactory,
				pouchesToGrant = pouchesToGrant
			};
			DetectCallingMod(out var name, out var guid);
			_registry[id].sourceMod = name;
			_registry[id].sourceModGuid = guid;
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)("[Registry] " + (isBinding ? "binding" : "trinket") + ": " + id + ((name != null) ? (" (from " + name + ")") : "")));
			}
		}

		internal static void DetectCallingMod(out string name, out string guid)
		{
			name = null;
			guid = null;
			try
			{
				Assembly assembly = typeof(TrinketRegistry).Assembly;
				StackTrace stackTrace = new StackTrace(0, fNeedFileInfo: false);
				for (int i = 0; i < stackTrace.FrameCount; i++)
				{
					Assembly assembly2 = (stackTrace.GetFrame(i)?.GetMethod())?.DeclaringType?.Assembly;
					if (assembly2 == null || assembly2 == assembly)
					{
						continue;
					}
					string name2 = assembly2.GetName().Name;
					if (string.IsNullOrEmpty(name2) || name2.StartsWith("UnityEngine") || name2.StartsWith("Unity.") || name2.StartsWith("System"))
					{
						continue;
					}
					switch (name2)
					{
					case "mscorlib":
					case "netstandard":
					case "Assembly-CSharp":
					case "Assembly-CSharp-firstpass":
						continue;
					}
					if (!name2.StartsWith("BepInEx") && !(name2 == "0Harmony"))
					{
						if (TryGetBepInPluginInfo(assembly2, out var name3, out var guid2))
						{
							name = ((!string.IsNullOrEmpty(name3)) ? name3 : name2);
							guid = guid2;
						}
						else
						{
							name = name2;
						}
						return;
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[Registry] DetectCallingMod failed: " + ex.Message));
				}
			}
		}

		private static bool TryGetBepInPluginInfo(Assembly a, out string name, out string guid)
		{
			name = null;
			guid = null;
			try
			{
				Type[] types = a.GetTypes();
				for (int i = 0; i < types.Length; i++)
				{
					object[] customAttributes = types[i].GetCustomAttributes(typeof(BepInPlugin), inherit: false);
					if (customAttributes != null && customAttributes.Length != 0)
					{
						object obj = customAttributes[0];
						BepInPlugin val = (BepInPlugin)((obj is BepInPlugin) ? obj : null);
						if (val != null)
						{
							name = val.Name;
							guid = val.GUID;
							return true;
						}
					}
				}
			}
			catch
			{
			}
			return false;
		}
	}
	internal static class ContortionIconCache
	{
		private static Sprite _cached;

		public static Sprite Get()
		{
			if ((Object)(object)_cached != (Object)null)
			{
				return _cached;
			}
			Trinket[] array = Resources.FindObjectsOfTypeAll<Trinket>();
			if (array == null)
			{
				return null;
			}
			foreach (Trinket val in array)
			{
				if ((Object)(object)val != (Object)null && ((Object)val).name == "Trinket_Totem" && (Object)(object)val.icon != (Object)null)
				{
					_cached = val.icon;
					return _cached;
				}
			}
			foreach (Trinket val2 in array)
			{
				if ((Object)(object)val2 != (Object)null && val2.title != null && val2.title.IndexOf("Contortion", StringComparison.OrdinalIgnoreCase) >= 0 && (Object)(object)val2.icon != (Object)null)
				{
					_cached = val2.icon;
					return _cached;
				}
			}
			return null;
		}
	}
	[HarmonyPatch(typeof(Trinket), "IsUnlocked")]
	public static class TrinketUnlockBypassPatch
	{
		[HarmonyPostfix]
		public static void Postfix(ref bool __result)
		{
			__result = true;
		}
	}
	[HarmonyPatch(typeof(UI_TrinketPicker), "SelectTrinket")]
	public static class MutexEnforcePatch
	{
		[HarmonyPrefix]
		public static void Prefix(UI_TrinketPicker __instance, Trinket t)
		{
			if ((Object)(object)__instance == (Object)null || __instance.selectedTrinkets == null || (Object)(object)t == (Object)null || TrinketRegistry._mutexGroups.Count == 0)
			{
				return;
			}
			TrinketRegistry.Entry entry = TrinketRegistry.FindEntryForTrinket(t);
			if (entry == null)
			{
				return;
			}
			List<string> list = null;
			foreach (KeyValuePair<string, List<string>> mutexGroup in TrinketRegistry._mutexGroups)
			{
				if (mutexGroup.Value.Contains(entry.id))
				{
					list = mutexGroup.Value;
					break;
				}
			}
			if (list == null || __instance.selectedTrinkets.Contains(t))
			{
				return;
			}
			for (int num = __instance.selectedTrinkets.Count - 1; num >= 0; num--)
			{
				TrinketRegistry.Entry entry2 = TrinketRegistry.FindEntryForTrinket(__instance.selectedTrinkets[num]);
				if (entry2 != null && list.Contains(entry2.id))
				{
					__instance.selectedTrinkets.RemoveAt(num);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Trinket), "GetDescription")]
	public static class TrinketCustomColorPatch
	{
		[HarmonyPostfix]
		public static void Postfix(Trinket __instance, ref string __result)
		{
			if (!((Object)(object)__instance == (Object)null))
			{
				TrinketRegistry.Entry entry = TrinketRegistry.FindEntryForTrinket(__instance);
				if (entry != null && !string.IsNullOrEmpty(entry.titleColor))
				{
					string text = (__instance.isBinding ? "Binding" : "Trinket");
					string text2 = (__instance.isBinding ? ("<shake a=0.01>" + __instance.description + "</shake>") : __instance.description);
					__result = "<color=grey>" + text + ":</color> <color=" + entry.titleColor + "><shimmer s=0.1>" + __instance.title + "</shimmer></color>. " + text2 + "\n<color=grey>" + __instance.flavorText + "</color>";
				}
			}
		}
	}
	[HarmonyPatch(typeof(Trinket), "Activate")]
	public static class StackableActivateRebuildPatch
	{
		[HarmonyPrefix]
		public static void Prefix(Trinket __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			TrinketRegistry.Entry entry = TrinketRegistry.FindEntryForTrinket(__instance);
			if (entry == null || (Object)(object)entry.runtime == (Object)null)
			{
				return;
			}
			if (entry.itemsToGrantFactory != null)
			{
				try
				{
					entry.runtime.itemsToGrant = entry.itemsToGrantFactory() ?? new List<Item_Object>();
				}
				catch (Exception ex)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("[ActivateRebuild] " + entry.id + " items: " + ex.Message));
					}
				}
			}
			if (entry.perksToGrantFactory == null)
			{
				return;
			}
			try
			{
				entry.runtime.perksToGrant = entry.perksToGrantFactory() ?? new List<Perk>();
			}
			catch (Exception ex2)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[ActivateRebuild] " + entry.id + " perks: " + ex2.Message));
				}
			}
		}
	}
	[HarmonyPatch(typeof(Trinket), "GetLockedDescription")]
	public static class LockedDescriptionNullGuardPatch
	{
		[HarmonyPrefix]
		public static bool Prefix(Trinket __instance, ref string __result)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return true;
			}
			if ((Object)(object)__instance.progressionUnlock == (Object)null && !__instance.comingSoon)
			{
				__result = __instance.GetDescription() + "\n<color=grey>(Locked by current selection.)</color>";
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(CL_AssetManager), "GetTrinketAsset")]
	public static class TrinketAssetLookupPatch
	{
		[HarmonyPostfix]
		public static void Postfix(string id, ref Trinket __result)
		{
			if ((Object)(object)__result != (Object)null || string.IsNullOrEmpty(id))
			{
				return;
			}
			string value = id.ToLowerInvariant();
			foreach (KeyValuePair<string, TrinketRegistry.Entry> item in TrinketRegistry._registry)
			{
				TrinketRegistry.Entry value2 = item.Value;
				if (!((Object)(object)value2.runtime == (Object)null) && !string.IsNullOrEmpty(value2.runtimeNameLower) && value2.runtimeNameLower.Contains(value))
				{
					__result = value2.runtime;
					break;
				}
			}
		}
	}
	[HarmonyPatch(typeof(UI_TrinketPicker), "ReloadTrinkets")]
	public static class TrinketInjectionPatch
	{
		private static readonly FieldInfoCache CurrentGamemodeField = new FieldInfoCache(typeof(UI_TrinketPicker), "currentGamemode");

		private static List<Trinket> _orderedTrinkets;

		private static List<Trinket> _orderedBindings;

		private static int _cachedRegistryCount = -1;

		[HarmonyPrefix]
		public static void Prefix(UI_TrinketPicker __instance)
		{
			object obj = CurrentGamemodeField.Get(__instance);
			InjectInto((M_Gamemode)(((obj is M_Gamemode) ? obj : null) ?? CL_GameManager.GetBaseGamemode()));
		}

		internal static void InjectInto(M_Gamemode gamemode)
		{
			if ((Object)(object)gamemode == (Object)null)
			{
				return;
			}
			PerkBindingAutoRegistrar.TryRun();
			ItemTrinketAutoRegistrar.TryRun();
			ArtifactTrinketAutoRegistrar.TryRun();
			ConsumableTrinketAutoRegistrar.TryRun();
			ClimbingItemTrinketAutoRegistrar.TryRun();
			MiscTrinketAutoRegistrar.TryRun();
			UnusedVanillaTrinketAutoRegistrar.TryRun();
			NoHammerBindingRegistrar.TryRun();
			if (TrinketRegistry._registry.Count == 0)
			{
				return;
			}
			if ((Object)(object)gamemode.availableTrinkets == (Object)null)
			{
				TrinketList val = ScriptableObject.CreateInstance<TrinketList>();
				((Object)val).name = "TrinketList_CiCi_Auto_" + (gamemode.gamemodeName ?? "unknown");
				val.trinkets = new List<Trinket>();
				val.bindings = new List<Trinket>();
				Object.DontDestroyOnLoad((Object)(object)val);
				gamemode.availableTrinkets = val;
			}
			if (gamemode.availableTrinkets.trinkets == null)
			{
				gamemode.availableTrinkets.trinkets = new List<Trinket>();
			}
			if (gamemode.availableTrinkets.bindings == null)
			{
				gamemode.availableTrinkets.bindings = new List<Trinket>();
			}
			gamemode.useGamemodeSettings = true;
			GamemodeSettingsAugmenter.Apply(gamemode);
			BuildRegistryRuntimes(gamemode);
			RebuildMasterListsIfStale();
			List<Trinket> trinkets = gamemode.availableTrinkets.trinkets;
			List<Trinket> bindings = gamemode.availableTrinkets.bindings;
			trinkets.Clear();
			bindings.Clear();
			foreach (Trinket orderedTrinket in _orderedTrinkets)
			{
				trinkets.Add(orderedTrinket);
			}
			foreach (Trinket orderedBinding in _orderedBindings)
			{
				bindings.Add(orderedBinding);
			}
			foreach (KeyValuePair<string, TrinketRegistry.Entry> item in TrinketRegistry._registry)
			{
				TrinketRegistry.Entry value = item.Value;
				if (!((Object)(object)value.runtime == (Object)null) && value.pinToVanilla)
				{
					List<Trinket> list = (value.isBinding ? bindings : trinkets);
					if (!list.Contains(value.runtime))
					{
						list.Add(value.runtime);
					}
				}
			}
			List<Trinket> list2 = new List<Trinket>();
			List<Trinket> list3 = new List<Trinket>();
			foreach (KeyValuePair<string, TrinketRegistry.Entry> item2 in TrinketRegistry._registry)
			{
				TrinketRegistry.Entry value2 = item2.Value;
				if (!((Object)(object)value2.runtime == (Object)null) && !value2.pinToVanilla)
				{
					(value2.isBinding ? list3 : list2).Add(value2.runtime);
				}
			}
			list2.Sort(CompareTrinkets);
			list3.Sort(CompareTrinkets);
			foreach (Trinket item3 in list2)
			{
				if (!trinkets.Contains(item3))
				{
					trinkets.Add(item3);
				}
			}
			foreach (Trinket item4 in list3)
			{
				if (!bindings.Contains(item4))
				{
					bindings.Add(item4);
				}
			}
		}

		internal static int CompareTrinkets(Trinket a, Trinket b)
		{
			TrinketRegistry.Entry entry = TrinketRegistry.FindEntryForTrinket(a);
			TrinketRegistry.Entry entry2 = TrinketRegistry.FindEntryForTrinket(b);
			bool flag = entry?.isFrameworkRegistered ?? false;
			bool flag2 = entry2?.isFrameworkRegistered ?? false;
			if (flag != flag2)
			{
				if (!flag)
				{
					return -1;
				}
				return 1;
			}
			int num = (int)(entry?.bucket ?? TrinketRegistry.Bucket.Vanilla);
			int num2 = (int)(entry2?.bucket ?? TrinketRegistry.Bucket.Vanilla);
			if (num != num2)
			{
				return num - num2;
			}
			int num3 = (int)(entry?.category ?? TrinketRegistry.Category.Other);
			int num4 = (int)(entry2?.category ?? TrinketRegistry.Category.Other);
			if (num3 != num4)
			{
				return num3 - num4;
			}
			bool flag3 = TrinketRegistry.IsGrey(entry?.titleColor);
			bool flag4 = TrinketRegistry.IsGrey(entry2?.titleColor);
			if (flag3 != flag4)
			{
				if (!flag3)
				{
					return 1;
				}
				return -1;
			}
			int num5 = entry?.tier ?? 0;
			int num6 = entry2?.tier ?? 0;
			if (num5 != num6)
			{
				return num5 - num6;
			}
			return string.Compare(a?.title ?? "", b?.title ?? "", StringComparison.OrdinalIgnoreCase);
		}

		private static void BuildRegistryRuntimes(M_Gamemode gamemode)
		{
			Sprite val = FindBorrowableIcon(gamemode.availableTrinkets?.trinkets);
			Sprite val2 = FindBorrowableIcon(gamemode.availableTrinkets?.bindings);
			foreach (KeyValuePair<string, TrinketRegistry.Entry> item in TrinketRegistry._registry)
			{
				TrinketRegistry.Entry value = item.Value;
				if ((Object)(object)value.runtime == (Object)null)
				{
					value.runtime = BuildTrinketSO(value);
					if ((Object)(object)value.runtime != (Object)null)
					{
						TrinketRegistry.RegisterRuntime(value.runtime, value);
					}
				}
				if ((Object)(object)value.runtime == (Object)null)
				{
					continue;
				}
				if ((Object)(object)value.runtime.icon == (Object)null)
				{
					Sprite val3 = (value.isBinding ? val2 : val);
					value.runtime.icon = value.icon ?? val3;
					value.runtime.lockIcon = value.runtime.icon;
				}
				if (value.itemsToGrantFactory != null)
				{
					try
					{
						value.runtime.itemsToGrant = value.itemsToGrantFactory() ?? new List<Item_Object>();
					}
					catch (Exception ex)
					{
						ManualLogSource log = Plugin.Log;
						if (log != null)
						{
							log.LogWarning((object)("[Registry] " + value.id + " items factory: " + ex.Message));
						}
					}
				}
				if (value.perksToGrantFactory == null)
				{
					continue;
				}
				try
				{
					value.runtime.perksToGrant = value.perksToGrantFactory() ?? new List<Perk>();
				}
				catch (Exception ex2)
				{
					ManualLogSource log2 = Plugin.Log;
					if (log2 != null)
					{
						log2.LogWarning((object)("[Registry] " + value.id + " perks factory: " + ex2.Message));
					}
				}
			}
		}

		private static void RebuildMasterListsIfStale()
		{
			if (_orderedTrinkets != null && _orderedBindings != null && _cachedRegistryCount == TrinketRegistry._registry.Count)
			{
				return;
			}
			List<Trinket> list = new List<Trinket>();
			List<Trinket> list2 = new List<Trinket>();
			HashSet<Trinket> hashSet = new HashSet<Trinket>();
			M_Gamemode val = FindOrderingSourceGamemode();
			if ((Object)(object)val != (Object)null && (Object)(object)val.availableTrinkets != (Object)null)
			{
				if (val.availableTrinkets.trinkets != null)
				{
					foreach (Trinket trinket in val.availableTrinkets.trinkets)
					{
						if (!((Object)(object)trinket == (Object)null) && hashSet.Add(trinket) && TrinketRegistry.FindEntryForTrinket(trinket) == null)
						{
							list.Add(trinket);
						}
					}
				}
				if (val.availableTrinkets.bindings != null)
				{
					foreach (Trinket binding in val.availableTrinkets.bindings)
					{
						if (!((Object)(object)binding == (Object)null) && hashSet.Add(binding) && TrinketRegistry.FindEntryForTrinket(binding) == null)
						{
							list2.Add(binding);
						}
					}
				}
			}
			Trinket[] array = Resources.FindObjectsOfTypeAll<Trinket>();
			if (array != null)
			{
				foreach (Trinket val2 in array)
				{
					if (!((Object)(object)val2 == (Object)null) && hashSet.Add(val2) && TrinketRegistry.FindEntryForTrinket(val2) == null)
					{
						if (val2.isBinding)
						{
							list2.Add(val2);
						}
						else
						{
							list.Add(val2);
						}
					}
				}
			}
			_orderedTrinkets = list;
			_orderedBindings = list2;
			_cachedRegistryCount = TrinketRegistry._registry.Count;
		}

		private static M_Gamemode FindOrderingSourceGamemode()
		{
			M_Gamemode[] array = Resources.FindObjectsOfTypeAll<M_Gamemode>();
			if (array == null)
			{
				return null;
			}
			foreach (M_Gamemode val in array)
			{
				if ((Object)(object)val != (Object)null && (Object)(object)val.availableTrinkets != (Object)null && val.gamemodeName == "Campaign")
				{
					return val;
				}
			}
			M_Gamemode result = null;
			int num = -1;
			foreach (M_Gamemode val2 in array)
			{
				if (!((Object)(object)val2 == (Object)null) && !((Object)(object)val2.availableTrinkets == (Object)null))
				{
					int num2 = (val2.availableTrinkets.trinkets?.Count ?? 0) + (val2.availableTrinkets.bindings?.Count ?? 0);
					if (num2 > num)
					{
						num = num2;
						result = val2;
					}
				}
			}
			return result;
		}

		private static Sprite FindBorrowableIcon(List<Trinket> source)
		{
			if (source == null)
			{
				return null;
			}
			foreach (Trinket item in source)
			{
				if (!((Object)(object)item == (Object)null) && !((Object)(object)item.icon == (Object)null) && !item.comingSoon && item.IsUnlocked())
				{
					return item.icon;
				}
			}
			foreach (Trinket item2 in source)
			{
				if ((Object)(object)item2 != (Object)null && (Object)(object)item2.icon != (Object)null)
				{
					return item2.icon;
				}
			}
			return null;
		}

		private static Trinket BuildTrinketSO(TrinketRegistry.Entry e)
		{
			Trinket obj = ScriptableObject.CreateInstance<Trinket>();
			((Object)obj).name = "Trinket_" + e.id;
			obj.title = e.title;
			obj.description = e.description;
			obj.flavorText = e.flavorText;
			obj.isBinding = e.isBinding;
			obj.cost = e.cost;
			obj.scoreMultiplierBonus = e.scoreMultiplierBonus;
			obj.scoreBonus = e.scoreBonus;
			obj.comingSoon = false;
			obj.settingBlacklist = new List<string>();
			obj.itemsToGrant = new List<Item_Object>();
			obj.perksToGrant = new List<Perk>();
			obj.pouchesToGrant = e.pouchesToGrant;
			obj.progressionUnlock = null;
			obj.icon = e.icon;
			obj.lockIcon = e.icon;
			Object.DontDestroyOnLoad((Object)(object)obj);
			return obj;
		}
	}
	internal static class GamemodeSettingsAugmenter
	{
		private static GamemodeSetting _hardmode;

		private static GamemodeSetting _ironknuckle;

		private static GamemodeSetting _unlimited;

		private static void EnsureLookup()
		{
			if ((Object)(object)_hardmode != (Object)null && (Object)(object)_ironknuckle != (Object)null && (Object)(object)_unlimited != (Object)null)
			{
				return;
			}
			GamemodeSetting[] array = Resources.FindObjectsOfTypeAll<GamemodeSetting>();
			if (array == null)
			{
				return;
			}
			foreach (GamemodeSetting val in array)
			{
				if (!((Object)(object)val == (Object)null) && !string.IsNullOrEmpty(val.id))
				{
					if ((Object)(object)_hardmode == (Object)null && val.id == "hardmode")
					{
						_hardmode = val;
					}
					else if ((Object)(object)_ironknuckle == (Object)null && val.id == "ironknuckle")
					{
						_ironknuckle = val;
					}
					else if ((Object)(object)_unlimited == (Object)null && val.id == "unlimited")
					{
						_unlimited = val;
					}
				}
			}
		}

		private static bool NameContains(M_Gamemode gm, string needle)
		{
			string text = gm?.gamemodeName;
			if (!string.IsNullOrEmpty(text))
			{
				return text.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		public static bool IsAugmentedMode(M_Gamemode gm)
		{
			if ((Object)(object)gm != (Object)null)
			{
				if (!NameContains(gm, "Parasite"))
				{
					return NameContains(gm, "Chimney");
				}
				return true;
			}
			return false;
		}

		public static void Apply(M_Gamemode gm)
		{
			if (!((Object)(object)gm == (Object)null))
			{
				EnsureLookup();
				if (gm.gamemodeSettings == null)
				{
					gm.gamemodeSettings = new List<GamemodeSetting>();
				}
				if (NameContains(gm, "Parasite"))
				{
					gm.allowHardmode = true;
					gm.allowIronKnuckle = true;
					AddIfMissing(gm, _hardmode);
					AddIfMissing(gm, _ironknuckle);
				}
				else if (NameContains(gm, "Chimney"))
				{
					AddIfMissing(gm, _unlimited);
				}
				CustomModePickerIntegration.InjectInto(gm);
			}
		}

		private static void AddIfMissing(M_Gamemode gm, GamemodeSetting setting)
		{
			if (!((Object)(object)setting == (Object)null) && !gm.gamemodeSettings.Contains(setting))
			{
				gm.gamemodeSettings.Add(setting);
			}
		}
	}
	[HarmonyPatch(typeof(UI_GamemodeScreen), "Initialize")]
	public static class GamemodeScreenInitInjectPatch
	{
		[HarmonyPrefix]
		public static void Prefix(M_Gamemode mode)
		{
			if (!((Object)(object)mode == (Object)null))
			{
				TrinketInjectionPatch.InjectInto(mode);
			}
		}

		[HarmonyPostfix]
		public static void Postfix(UI_GamemodeScreen __instance)
		{
			if (__instance?.activePanels == null)
			{
				return;
			}
			foreach (KeyValuePair<string, UI_GamemodeScreen_Panel> activePanel in __instance.activePanels)
			{
				UI_GamemodeScreen_Panel value = activePanel.Value;
				if ((Object)(object)value == (Object)null)
				{
					continue;
				}
				UI_TrinketPicker[] componentsInChildren = ((Component)value).GetComponentsInChildren<UI_TrinketPicker>(true);
				foreach (UI_TrinketPicker val in componentsInChildren)
				{
					if ((Object)(object)val == (Object)null)
					{
						continue;
					}
					if ((Object)(object)val.parentPanel == (Object)null)
					{
						val.parentPanel = value;
					}
					try
					{
						val.Initialize();
					}
					catch (Exception ex)
					{
						ManualLogSource log = Plugin.Log;
						if (log != null)
						{
							log.LogWarning((object)("picker init failed on " + ((Object)value).name + ": " + ex.Message));
						}
					}
				}
			}
		}
	}
	internal static class GamemodeSettingUnlockBypass
	{
		private static readonly FieldInfoCache PanelField = new FieldInfoCache(typeof(UI_GamemodeSetting), "gamemodePanel");

		public static UI_GamemodeScreen_Panel GetPanel(UI_GamemodeSetting inst)
		{
			object obj = PanelField.Get(inst);
			return (UI_GamemodeScreen_Panel)((obj is UI_GamemodeScreen_Panel) ? obj : null);
		}

		public static void ForceUnlocked(UI_GamemodeSetting inst)
		{
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0129: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)inst == (Object)null || (Object)(object)inst.gamemodeSetting == (Object)null || (Object)(object)inst.toggle == (Object)null)
			{
				return;
			}
			object obj = PanelField.Get(inst);
			object obj2 = ((obj is UI_GamemodeScreen_Panel) ? obj : null);
			M_Gamemode val = ((obj2 != null) ? ((UI_GamemodeScreen_Panel)obj2).GetGamemode() : null);
			GamemodeSetting gamemodeSetting = inst.gamemodeSetting;
			if (!GamemodeSettingsAugmenter.IsAugmentedMode(val) && (Object)(object)val != (Object)null && gamemodeSetting.exclusiveSettings != null)
			{
				foreach (string exclusiveSetting in gamemodeSetting.exclusiveSettings)
				{
					if (val.HasActiveSetting(exclusiveSetting) && !val.HasActiveSetting(gamemodeSetting.id))
					{
						return;
					}
				}
			}
			if ((Object)(object)inst.lockObject != (Object)null)
			{
				inst.lockObject.SetActive(false);
			}
			((Selectable)inst.toggle).interactable = true;
			if ((Object)(object)inst.descriptionText != (Object)null)
			{
				inst.descriptionText.text = gamemodeSetting.description;
			}
			Color val2 = gamemodeSetting.color;
			if (!inst.toggle.isOn)
			{
				val2 *= Color.grey;
			}
			if ((Object)(object)inst.outline != (Object)null)
			{
				((Graphic)inst.outline).color = val2;
			}
			if ((Object)(object)((Selectable)inst.toggle).targetGraphic != (Object)null)
			{
				((Selectable)inst.toggle).targetGraphic.color = val2;
			}
			if ((Object)(object)inst.toggle.graphic != (Object)null)
			{
				inst.toggle.graphic.color = val2;
			}
			if ((Object)(object)inst.titleText != (Object)null)
			{
				((Graphic)inst.titleText).color = val2;
			}
			if ((Object)(object)inst.descriptionText != (Object)null)
			{
				((Graphic)inst.descriptionText).color = val2;
			}
			if ((Object)(object)inst.unlockHint != (Object)null)
			{
				((Graphic)inst.unlockHint).color = val2;
			}
		}
	}
	[HarmonyPatch(typeof(UI_GamemodeSetting), "Initialize")]
	public static class GamemodeSettingInitUnlockBypassPatch
	{
		[HarmonyPostfix]
		public static void Postfix(UI_GamemodeSetting __instance)
		{
			GamemodeSettingUnlockBypass.ForceUnlocked(__instance);
			CustomModeCreditHover.AttachTo(__instance);
		}
	}
	[HarmonyPatch(typeof(UI_GamemodeSetting), "UpdateColor")]
	public static class GamemodeSettingUpdateColorUnlockBypassPatch
	{
		[HarmonyPostfix]
		public static void Postfix(UI_GamemodeSetting __instance)
		{
			GamemodeSettingUnlockBypass.ForceUnlocked(__instance);
		}
	}
	internal sealed class FieldInfoCache
	{
		private readonly FieldInfo _field;

		public FieldInfoCache(Type type, string name)
		{
			_field = AccessTools.Field(type, name);
		}

		public object Get(object instance)
		{
			return _field?.GetValue(instance);
		}
	}
	internal static class PickerReflection
	{
		public static readonly FieldInfoCache DescriptionTextField = new FieldInfoCache(typeof(UI_TrinketPicker), "descriptionText");

		public static readonly FieldInfoCache ParentPickerField = new FieldInfoCache(typeof(UI_TrinketPicker_Icon), "parentPicker");

		public static bool HasDescriptionText(UI_TrinketPicker picker)
		{
			if ((Object)(object)picker == (Object)null)
			{
				return false;
			}
			object obj = DescriptionTextField.Get(picker);
			Object val = (Object)((obj is Object) ? obj : null);
			if (val != null)
			{
				return val != (Object)null;
			}
			return false;
		}

		public static UI_TrinketPicker GetParentPicker(UI_TrinketPicker_Icon icon)
		{
			if (!((Object)(object)icon == (Object)null))
			{
				object obj = ParentPickerField.Get(icon);
				return (UI_TrinketPicker)((obj is UI_TrinketPicker) ? obj : null);
			}
			return null;
		}
	}
	[HarmonyPatch(typeof(UI_TrinketPicker), "HideDescription")]
	public static class HideDescriptionNullGuardPatch
	{
		[HarmonyPrefix]
		public static bool Prefix(UI_TrinketPicker __instance)
		{
			return PickerReflection.HasDescriptionText(__instance);
		}
	}
	[HarmonyPatch(typeof(UI_TrinketPicker), "ShowDescription")]
	public static class ShowDescriptionNullGuardPatch
	{
		[HarmonyPrefix]
		public static bool Prefix(UI_TrinketPicker __instance)
		{
			return PickerReflection.HasDescriptionText(__instance);
		}
	}
	[HarmonyPatch(typeof(UI_TrinketPicker), "ShowTrinketDescription")]
	public static class ShowTrinketDescriptionNullGuardPatch
	{
		[HarmonyPrefix]
		public static bool Prefix(UI_TrinketPicker __instance, Trinket t)
		{
			if ((Object)(object)t != (Object)null)
			{
				return PickerReflection.HasDescriptionText(__instance);
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(UI_TrinketPicker_Icon), "OnPointerEnter")]
	public static class IconPointerEnterNullGuardPatch
	{
		[HarmonyPrefix]
		public static bool Prefix(UI_TrinketPicker_Icon __instance)
		{
			if ((Object)(object)PickerReflection.GetParentPicker(__instance) != (Object)null)
			{
				return (Object)(object)__instance.trinket != (Object)null;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(UI_TrinketPicker_Icon), "OnPointerExit")]
	public static class IconPointerExitNullGuardPatch
	{
		[HarmonyPrefix]
		public static bool Prefix(UI_TrinketPicker_Icon __instance)
		{
			return (Object)(object)PickerReflection.GetParentPicker(__instance) != (Object)null;
		}
	}
	[HarmonyPatch(typeof(UI_TrinketPicker_Icon), "OnSelect")]
	public static class IconSelectNullGuardPatch
	{
		[HarmonyPrefix]
		public static bool Prefix(UI_TrinketPicker_Icon __instance)
		{
			if ((Object)(object)PickerReflection.GetParentPicker(__instance) != (Object)null)
			{
				return (Object)(object)__instance.trinket != (Object)null;
			}
			return false;
		}
	}
	[HarmonyPatch(typeof(UI_TrinketPicker_Icon), "OnDeselect")]
	public static class IconDeselectNullGuardPatch
	{
		[HarmonyPrefix]
		public static bool Prefix(UI_TrinketPicker_Icon __instance)
		{
			return (Object)(object)PickerReflection.GetParentPicker(__instance) != (Object)null;
		}
	}
	[HarmonyPatch(typeof(UI_TrinketPicker_Icon), "OnClick")]
	public static class IconClickNullGuardPatch
	{
		[HarmonyPrefix]
		public static bool Prefix(UI_TrinketPicker_Icon __instance)
		{
			if ((Object)(object)PickerReflection.GetParentPicker(__instance) != (Object)null)
			{
				return (Object)(object)__instance.trinket != (Object)null;
			}
			return false;
		}
	}
	public class PerkBindingClickOverride : MonoBehaviour, IPointerDownHandler, IEventSystemHandler
	{
		public string bindingId;

		public TextMeshProUGUI stackText;

		private int _lastProcessedFrame = -1;

		private static readonly MethodInfo _updateTrinketActivation = AccessTools.Method(typeof(UI_TrinketPicker), "UpdateTrinketActivation", (Type[])null, (Type[])null);

		public void OnPointerDown(PointerEventData eventData)
		{
			int frameCount = Time.frameCount;
			if (frameCount == _lastProcessedFrame)
			{
				return;
			}
			_lastProcessedFrame = frameCount;
			bool mouseButtonDown = Input.GetMouseButtonDown(0);
			bool mouseButtonDown2 = Input.GetMouseButtonDown(1);
			bool flag = mouseButtonDown2 && !mouseButtonDown;
			bool flag2 = mouseButtonDown && !mouseButtonDown2;
			if ((!flag && !flag2) || !TrinketRegistry._registry.TryGetValue(bindingId, out var value))
			{
				return;
			}
			UI_TrinketPicker_Icon component = ((Component)this).GetComponent<UI_TrinketPicker_Icon>();
			if ((Object)(object)component == (Object)null || (Object)(object)component.trinket == (Object)null)
			{
				return;
			}
			UI_TrinketPicker parentPicker = PickerReflection.GetParentPicker(component);
			if ((Object)(object)parentPicker == (Object)null)
			{
				return;
			}
			bool flag3 = parentPicker.selectedTrinkets != null && parentPicker.selectedTrinkets.Contains(component.trinket);
			bool flag4 = false;
			if (flag2)
			{
				if (!flag3)
				{
					value.stackCount = 1;
					parentPicker.SelectTrinket(component.trinket);
				}
				else if (value.stackCount < value.maxStacks)
				{
					value.stackCount++;
					flag4 = true;
				}
			}
			else if (flag && flag3)
			{
				if (value.stackCount > 1)
				{
					value.stackCount--;
					flag4 = true;
				}
				else
				{
					value.stackCount = 1;
					parentPicker.SelectTrinket(component.trinket);
				}
			}
			if (flag4)
			{
				try
				{
					_updateTrinketActivation?.Invoke(parentPicker, null);
				}
				catch (Exception ex)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)("[Stack] activation refresh failed: " + ex.Message));
					}
				}
			}
			if ((Object)(object)value.runtime != (Object)null)
			{
				if (value.perksToGrantFactory != null)
				{
					try
					{
						value.runtime.perksToGrant = value.perksToGrantFactory();
					}
					catch (Exception ex2)
					{
						ManualLogSource log2 = Plugin.Log;
						if (log2 != null)
						{
							log2.LogWarning((object)("[Stack] perksToGrant rebuild failed for " + value.id + ": " + ex2.Message));
						}
					}
				}
				if (value.itemsToGrantFactory != null)
				{
					try
					{
						value.runtime.itemsToGrant = value.itemsToGrantFactory();
					}
					catch (Exception ex3)
					{
						ManualLogSource log3 = Plugin.Log;
						if (log3 != null)
						{
							log3.LogWarning((object)("[Stack] itemsToGrant rebuild failed for " + value.id + ": " + ex3.Message));
						}
					}
				}
			}
			UpdateStackVisual(value);
		}

		private void UpdateStackVisual(TrinketRegistry.Entry entry)
		{
			if (!((Object)(object)stackText == (Object)null))
			{
				((TMP_Text)stackText).text = ((entry.stackCount > 1) ? $"x{entry.stackCount}" : "");
			}
		}
	}
	[HarmonyPatch(typeof(UI_TrinketPicker_Icon), "SetTrinket")]
	public static class PerkBindingIconAttachPatch
	{
		[HarmonyPostfix]
		public static void Postfix(UI_TrinketPicker_Icon __instance, Trinket t)
		{
			if ((Object)(object)__instance == (Object)null || (Object)(object)t == (Object)null || string.IsNullOrEmpty(((Object)t).name))
			{
				return;
			}
			TrinketRegistry.Entry entry = TrinketRegistry.FindEntryForTrinket(t);
			if (entry != null && entry.maxStacks > 1)
			{
				Button component = ((Component)__instance).GetComponent<Button>();
				if ((Object)(object)component != (Object)null)
				{
					((UnityEventBase)component.onClick).RemoveAllListeners();
				}
				PerkBindingClickOverride perkBindingClickOverride = ((Component)__instance).GetComponent<PerkBindingClickOverride>() ?? ((Component)__instance).gameObject.AddComponent<PerkBindingClickOverride>();
				perkBindingClickOverride.bindingId = entry.id;
				if (entry.maxStacks > 1)
				{
					perkBindingClickOverride.stackText = EnsureStackText(((Component)__instance).transform);
					((TMP_Text)perkBindingClickOverride.stackText).text = ((entry.stackCount > 1) ? $"x{entry.stackCount}" : "");
				}
			}
		}

		private static TextMeshProUGUI EnsureStackText(Transform iconRoot)
		{
			//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_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			Transform val = iconRoot.Find("CiCi_StackCount");
			if ((Object)(object)val != (Object)null)
			{
				TextMeshProUGUI component = ((Component)val).GetComponent<TextMeshProUGUI>();
				if ((Object)(object)component != (Object)null)
				{
					return component;
				}
			}
			GameObject val2 = new GameObject("CiCi_StackCount", new Type[1] { typeof(RectTransform) });
			RectTransform val3 = (RectTransform)val2.transform;
			((Transform)val3).SetParent(iconRoot, false);
			val3.anchorMin = new Vector2(1f, 1f);
			val3.anchorMax = new Vector2(1f, 1f);
			val3.pivot = new Vector2(1f, 1f);
			val3.anchoredPosition = new Vector2(-2f, -2f);
			val3.sizeDelta = new Vector2(40f, 20f);
			TextMeshProUGUI obj = val2.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj).alignment = (TextAlignmentOptions)260;
			((TMP_Text)obj).fontSize = 16f;
			((Graphic)obj).color = Color.white;
			((Graphic)obj).raycastTarget = false;
			((TMP_Text)obj).text = "";
			return obj;
		}
	}
	[HarmonyPatch(typeof(UI_TrinketPicker), "UpdatePips")]
	public static class PipsStackInflatePatch
	{
		[HarmonyPrefix]
		public static void Prefix(UI_TrinketPicker __instance, int totalBudget, ref int usedBudget)
		{
			if ((Object)(object)__instance == (Object)null || __instance.selectedTrinkets == null)
			{
				return;
			}
			int num = 0;
			foreach (Trinket selectedTrinket in __instance.selectedTrinkets)
			{
				if (!((Object)(object)selectedTrinket == (Object)null) && !selectedTrinket.isBinding)
				{
					TrinketRegistry.Entry entry = TrinketRegistry.FindEntryForTrinket(selectedTrinket);
					num += ((entry == null) ? 1 : Mathf.Max(1, entry.stackCount));
				}
			}
			usedBudget = num;
		}
	}
	[HarmonyPatch(typeof(UI_TrinketPicker), "UpdatePips")]
	public static class PipsOverflowPatch
	{
		private const int VisibleCap = 5;

		private const string OverflowName = "CiCi_PipOverflow";

		private static readonly FieldInfo PipsField = AccessTools.Field(typeof(UI_TrinketPicker), "pips");

		[HarmonyPostfix]
		public static void Postfix(UI_TrinketPicker __instance, int totalBudget, int usedBudget)
		{
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)__instance == (Object)null || (Object)(object)__instance.pipHolder == (Object)null || !(PipsField?.GetValue(__instance) is List<Image> list))
			{
				return;
			}
			for (int i = 0; i < list.Count; i++)
			{
				if (!((Object)(object)list[i] == (Object)null))
				{
					bool flag = i < 5;
					if (((Component)list[i]).gameObject.activeSelf != flag)
					{
						((Component)list[i]).gameObject.SetActive(flag);
					}
				}
			}
			int num = Mathf.Max(totalBudget, usedBudget) - 5;
			TextMeshProUGUI val = EnsureOverflowText(__instance.pipHolder);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Transform parent = ((TMP_Text)val).transform.parent;
			if ((Object)(object)parent != (Object)null)
			{
				parent.SetAsLastSibling();
			}
			if (num > 0)
			{
				((TMP_Text)val).text = $"[+{num}]";
				((Graphic)val).color = ((usedBudget > totalBudget) ? Color.red : Color.white);
				if ((Object)(object)parent != (Object)null && !((Component)parent).gameObject.activeSelf)
				{
					((Component)parent).gameObject.SetActive(true);
				}
				if (!((Component)val).gameObject.activeSelf)
				{
					((Component)val).gameObject.SetActive(true);
				}
				RectTransform rectTransform = ((TMP_Text)val).rectTransform;
				if ((Object)(object)rectTransform != (Object)null)
				{
					rectTransform.anchoredPosition = new Vector2(8f, -5f);
				}
			}
			else if ((Object)(object)parent != (Object)null && ((Component)parent).gameObject.activeSelf)
			{
				((Component)parent).gameObject.SetActive(false);
			}
		}

		private static TextMeshProUGUI EnsureOverflowText(Transform pipHolder)
		{
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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: Expected O, but got Unknown
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			Transform obj = pipHolder.Find("CiCi_PipOverflow");
			RectTransform val = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			TextMeshProUGUI componentInChildren;
			if ((Object)(object)val != (Object)null)
			{
				componentInChildren = ((Component)val).GetComponentInChildren<TextMeshProUGUI>(true);
				if ((Object)(object)componentInChildren != (Object)null)
				{
					return componentInChildren;
				}
			}
			else
			{
				GameObject val2 = new GameObject("CiCi_PipOverflow", new Type[1] { typeof(RectTransform) });
				val = (RectTransform)val2.transform;
				((Transform)val).SetParent(pipHolder, false);
				val.sizeDelta = new Vector2(50f, 22f);
				LayoutElement obj2 = val2.AddComponent<LayoutElement>();
				obj2.preferredWidth = 50f;
				obj2.preferredHeight = 22f;
				obj2.flexibleWidth = 0f;
				obj2.flexibleHeight = 0f;
			}
			GameObject val3 = new GameObject("Text", new Type[1] { typeof(RectTransform) });
			RectTransform val4 = (RectTransform)val3.transform;
			((Transform)val4).SetParent((Transform)(object)val, false);
			val4.anchorMin = Vector2.zero;
			val4.anchorMax = Vector2.one;
			val4.pivot = new Vector2(0.5f, 0.5f);
			val4.anchoredPosition = Vector2.zero;
			val4.sizeDelta = Vector2.zero;
			componentInChildren = val3.AddComponent<TextMeshProUGUI>();
			((TMP_Text)componentInChildren).fontSize = 18f;
			((TMP_Text)componentInChildren).alignment = (TextAlignmentOptions)4097;
			((Graphic)componentInChildren).color = Color.white;
			((TMP_Text)componentInChildren).fontStyle = (FontStyles)1;
			((Graphic)componentInChildren).raycastTarget = false;
			((TMP_Text)componentInChildren).text = "";
			UI_TrinketPicker componentInParent = ((Component)pipHolder).GetComponentInParent<UI_TrinketPicker>();
			TMP_Text val5 = (((Object)(object)componentInParent != (Object)null) ? componentInParent.costText : null);
			if ((Object)(object)val5 != (Object)null && (Object)(object)val5.font != (Object)null)
			{
				((TMP_Text)componentInChildren).font = val5.font;
			}
			return componentInChildren;
		}
	}
	public static class ItemTrinketAutoRegistrar
	{
		private struct ItemDef
		{
			public string title;

			public string prefabName;

			public string color;

			public string description;

			public string flavor;
		}

		private static bool _done;

		private const string LightGrey = "#D3D3D3";

		private const string MutexGroup = "tools";

		private static readonly ItemDef[] _tools = new ItemDef[5]
		{
			new ItemDef
			{
				title = "Cryo-Gun",
				prefabName = "Item_Cryogun",
				color = "#8DDDF5",
				description = "Start with a cryo-gun.",
				flavor = ""
			},
			new ItemDef
			{
				title = "Flare Gun",
				prefabName = "Item_Flaregun",
				color = "#D3D3D3",
				description = "Start with a flare gun.",
				flavor = ""
			},
			new ItemDef
			{
				title = "Flashlight",
				prefabName = "Item_Flashlight",
				color = "#D3D3D3",
				description = "Start with a flashlight.",
				flavor = ""
			},
			new ItemDef
			{
				title = "Wrench",
				prefabName = "Item_Hammer_Cosmetic_Wrench",
				color = "#18420F",
				description = "Start with a wrench.",
				flavor = ""
			},
			new ItemDef
			{
				title = "Scanner",
				prefabName = "Item_EntityScanner",
				color = "#18420F",
				description = "Start with an entity scanner.",
				flavor = ""
			}
		};

		internal static void TryRun()
		{
			if (_done)
			{
				return;
			}
			List<(ItemDef, Item_Object)> list = new List<(ItemDef, Item_Object)>();
			ItemDef[] tools = _tools;
			for (int i = 0; i < tools.Length; i++)
			{
				ItemDef item = tools[i];
				Item_Object val = null;
				try
				{
					GameObject assetGameObject = CL_AssetManager.GetAssetGameObject(item.prefabName, "");
					val = (((Object)(object)assetGameObject != (Object)null) ? assetGameObject.GetComponent<Item_Object>() : null);
				}
				catch
				{
				}
				if ((Object)(object)val == (Object)null)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogInfo((object)("[AutoTools] '" + item.prefabName + "' not yet loaded — deferring"));
					}
					return;
				}
				list.Add((item, val));
			}
			Sprite val2 = ContortionIconCache.Get();
			List<string> list2 = new List<string>();
			foreach (var item4 in list)
			{
				ItemDef item2 = item4.Item1;
				Item_Object item3 = item4.Item2;
				string text = "cici_tool_" + item2.prefabName;
				if (TrinketRegistry._registry.ContainsKey(text))
				{
					list2.Add(text);
					continue;
				}
				Sprite icon = val2 ?? item3.itemData?.normalSprite;
				Item_Object ioRef = item3;
				TrinketRegistry.RegisterTrinket(text, item2.title, item2.description, item2.flavor, 1, 0f, 0f, icon, () => new List<Item_Object> { ioRef });
				if (TrinketRegistry._registry.TryGetValue(text, out var value))
				{
					value.titleColor = item2.color;
					value.category = TrinketRegistry.Category.Tool;
					value.bucket = TrinketRegistry.BucketFromColor(item2.color);
					value.isFrameworkRegistered = true;
					value.isVanillaContent = true;
				}
				list2.Add(text);
			}
			TrinketRegistry.RegisterMutexGroup("tools", list2.ToArray());
			_done = true;
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)string.Format("[AutoTools] Registered {0} tool trinkets in mutex group '{1}'", list2.Count, "tools"));
			}
		}
	}
	public static class NoHammerBindingRegistrar
	{
		private static bool _done;

		public const string BindingId = "cici_nohammer";

		private static Sprite _icon;

		private static bool _cachedActive;

		private static bool _cacheValid;

		public static bool Active
		{
			get
			{
				if (!_cacheValid)
				{
					Recompute();
				}
				return _cachedActive;
			}
		}

		public static void Invalidate()
		{
			_cacheValid = false;
		}

		private static void Recompute()
		{
			_cachedActive = ComputeActiveNow();
			_cacheValid = true;
		}

		private static bool ComputeActiveNow()
		{
			try
			{
				M_Gamemode currentGamemode = CL_GameManager.GetCurrentGamemode();
				if ((Object)(object)currentGamemode == (Object)null)
				{
					return false;
				}
				SaveData saveData = StatManager.saveData;
				List<string> list = ((saveData != null) ? saveData.GetGamemodeTrinkets(currentGamemode.GetGamemodeName(true)) : null);
				if (list == null)
				{
					return false;
				}
				foreach (string item in list)
				{
					if (!string.IsNullOrEmpty(item) && item.ToLowerInvariant().Contains("cici_nohammer"))
					{
						return true;
					}
				}
			}
			catch
			{
			}
			return false;
		}

		internal static void TryRun()
		{
			if (_done)
			{
				return;
			}
			if (TrinketRegistry._registry.ContainsKey("cici_nohammer"))
			{
				_done = true;
				return;
			}
			if ((Object)(object)_icon == (Object)null)
			{
				_icon = TryLoadIcon("No_Hammer_Icon.png");
			}
			TrinketRegistry.RegisterBinding("cici_nohammer", "No Hammer", "Start the run without a hammer.", "", 1, 0f, 0f, _icon ?? ContortionIconCache.Get(), () => new List<Item_Object>());
			if (TrinketRegistry._registry.TryGetValue("cici_nohammer", out var value))
			{
				value.titleColor = "#D3D3D3";
				value.category = TrinketRegistry.Category.Perk;
				value.bucket = TrinketRegistry.Bucket.Vanilla;
				value.isFrameworkRegistered = true;
			}
			_done = true;
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"[NoHammer] Registered binding");
			}
		}

		private static Sprite TryLoadIcon(string filename)
		{
			//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_003d: Expected O, but got Unknown
			//IL_0071: 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)
			try
			{
				string path = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), filename);
				if (!File.Exists(path))
				{
					return null;
				}
				byte[] array = File.ReadAllBytes(path);
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false)
				{
					filterMode = (FilterMode)0
				};
				if (!ImageConversion.LoadImage(val, array))
				{
					return null;
				}
				((Texture)val).wrapMode = (TextureWrapMode)1;
				((Object)val).name = filename;
				return Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f, 0u, (SpriteMeshType)0);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[NoHammer] icon load failed: " + ex.Message));
				}
				return null;
			}
		}
	}
	[HarmonyPatch(typeof(Item_Object), "Start")]
	public static class NoHammerBanItemSpawnPatch
	{
		[HarmonyPostfix]
		public static void Postfix(Item_Object __instance)
		{
			if (NoHammerBindingRegistrar.Active && __instance?.itemData != null && __instance.itemData.prefabName == "Item_Hammer")
			{
				((Component)__instance).gameObject.SetActive(false);
			}
		}
	}
	[HarmonyPatch(typeof(M_Gamemode), "StartFreshGamemode")]
	public static class NoHammerCacheStartInvalidatePatch
	{
		[HarmonyPostfix]
		public static void Postfix()
		{
			NoHammerBindingRegistrar.Invalidate();
		}
	}
	[HarmonyPatch(typeof(UI_TrinketPicker), "SelectTrinket")]
	public static class NoHammerCacheSelectInvalidatePatch
	{
		[HarmonyPostfix]
		public static void Postfix()
		{
			NoHammerBindingRegistrar.Invalidate();
		}
	}
	[HarmonyPatch(typeof(SaveData), "GetGamemodeTrinkets")]
	public static class GetGamemodeTrinketsLogSilencePatch
	{
		[HarmonyPrefix]
		public static bool Prefix(SaveData __instance, string gameModeName, ref List<string> __result)
		{
			GameModeData gameMode = __instance.GetGameMode(gameModeName);
			__result = ((gameMode != null && gameMode.activeTrinkets != null) ? gameMode.activeTrinkets : new List<string>());
			return false;
		}
	}
	public static class ConsumableTrinketAutoRegistrar
	{
		private struct ConsumableDef
		{
			public string title;

			public string prefabName;

			public string color;

			public string description;
		}

		private static bool _done;

		private const string LightGrey = "#D3D3D3";

		private const int MaxStacks = 12;

		private static readonly ConsumableDef[] _items = new ConsumableDef[13]
		{
			new ConsumableDef
			{
				title = "Blink Eye",
				prefabName = "Item_BlinkEye",
				color = "#ED4040",
				description = "Start with Blink Eye(s)."
			},
			new ConsumableDef
			{
				title = "Canned Food",
				prefabName = "Item_Beans",
				color = "#D3D3D3",
				description = "Start with canned food."
			},
			new ConsumableDef
			{
				title = "Delta-0052",
				prefabName = "Item_Beans_Periphery",
				color = "#8EF6DD",
				description = "Start with Delta-0052."
			},
			new ConsumableDef
			{
				title = "Food Bar",
				prefabName = "Item_Food_Bar",
				color = "#D3D3D3",
				description = "Start with food bars."
			},
			new ConsumableDef
			{
				title = "Grub",
				prefabName = "Denizen_SlugGrub",
				color = "#D3D3D3",
				description = "Start with grubs."
			},
			new ConsumableDef
			{
				title = "Injector",
				prefabName = "Item_Injector",
				color = "#D3D3D3",
				description = "Start with injectors."
			},
			new ConsumableDef
			{
				title = "Inoculator",
				prefabName = "Item_Inoculator",
				color = "#18420F",
				description = "Start with inoculators."
			},
			new ConsumableDef
			{
				title = "Lemon Roach",
				prefabName = "Denizen_Roach_Lemon",
				color = "#FDED56",
				description = "Start with lemon roaches."
			},
			new ConsumableDef
			{
				title = "Milk",
				prefabName = "Item_Milk",
				color = "#8DDDF5",
				description = "Start with milk cartons."
			},
			new ConsumableDef
			{
				title = "Pills",
				prefabName = "Item_Pillbottle",
				color = "#D3D3D3",
				description = "Start with pill bottles."
			},
			new ConsumableDef
			{
				title = "Hot Cocoa",
				prefabName = "Item_Cocoa_Full",
				color = "#8DDDF5",
				description = "Start with hot cocoa."
			},
			new ConsumableDef
			{
				title = "Cookie",
				prefabName = "Item_Food_Cookie",
				color = "#8DDDF5",
				description = "Start with cookies."
			},
			new ConsumableDef
			{
				title = "Candy Cauldron",
				prefabName = "Item_CandyCauldron",
				color = "#FFD454",
				description = "Start with candy cauldrons."
			}
		};

		internal static void TryRun()
		{
			if (_done)
			{
				return;
			}
			Sprite val = ContortionIconCache.Get();
			bool flag = false;
			bool flag2 = true;
			ConsumableDef[] items = _items;
			for (int i = 0; i < items.Length; i++)
			{
				ConsumableDef consumableDef = items[i];
				string text = "cici_consumable_" + consumableDef.prefabName;
				if (TrinketRegistry._registry.ContainsKey(text))
				{
					flag = true;
					continue;
				}
				Item_Object val2 = null;
				try
				{
					GameObject assetGameObject = CL_AssetManager.GetAssetGameObject(consumableDef.prefabName, "");
					val2 = (((Object)(object)assetGameObject != (Object)null) ? assetGameObject.GetComponent<Item_Object>() : null);
				}
				catch
				{
				}
				if ((Object)(object)val2 == (Object)null)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogInfo((object)("[AutoConsumables] '" + consumableDef.prefabName + "' not yet loaded — skipping"));
					}
					flag2 = false;
					continue;
				}
				flag = true;
				Sprite icon = val ?? val2.itemData?.normalSprite;
				Item_Object ioRef = val2;
				string idCopy = text;
				TrinketRegistry.RegisterTrinket(text, consumableDef.title, consumableDef.description, "", 1, 0f, 0f, icon, delegate
				{
					TrinketRegistry.Entry value2;
					int num = ((!TrinketRegistry._registry.TryGetValue(idCopy, out value2)) ? 1 : Mathf.Max(1, value2.stackCount));
					List<Item_Object> list = new List<Item_Object>(num);
					for (int j = 0; j < num; j++)
					{
						list.Add(ioRef);
					}
					return list;
				});
				if (TrinketRegistry._registry.TryGetValue(text, out var value))
				{
					value.titleColor = consumableDef.color;
					value.maxStacks = 12;
					value.stackCount = 1;
					value.category = TrinketRegistry.Category.Consumable;
					value.bucket = TrinketRegistry.BucketFromColor(consumableDef.color);
					value.isFrameworkRegistered = true;
					value.isVanillaContent = true;
				}
			}
			if (flag2)
			{
				_done = true;
			}
			if (flag)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)$"[AutoConsumables] Pass complete — allResolved={flag2}");
				}
			}
		}
	}
	public static class ClimbingItemTrinketAutoRegistrar
	{
		private struct ClimbingItemDef
		{
			public string title;

			public string prefabName;

			public string color;

			public string description;
		}

		private static bool _done;

		private const string LightGrey = "#D3D3D3";

		private const int MaxStacks = 12;

		private static readonly ClimbingItemDef[] _items = new ClimbingItemDef[10]
		{
			new ClimbingItemDef
			{
				title = "Rope Rebar",
				prefabName = "Item_RebarRope",
				color = "#D3D3D3",
				description = "Start with rope rebar."
			},
			new ClimbingItemDef
			{
				title = "Explosive Rebar",
				prefabName = "Item_Rebar_Explosive",
				color = "#D3D3D3",
				description = "Start with explosive rebar."
			},
			new ClimbingItemDef
			{
				title = "Rope",
				prefabName = "Item_Rope",
				color = "#D3D3D3",
				description = "Start with rope."
			},
			new ClimbingItemDef
			{
				title = "Auto Piton",
				prefabName = "Item_AutoPiton",
				color = "#D3D3D3",
				description = "Start with auto pitons."
			},
			new ClimbingItemDef
			{
				title = "Brick",
				prefabName = "Item_Rubble",
				color = "#D3D3D3",
				description = "Start with bricks."
			},
			new ClimbingItemDef
			{
				title = "Piton",
				prefabName = "Item_Piton",
				color = "#D3D3D3",
				description = "Start with pitons."
			},
			new ClimbingItemDef
			{
				title = "Rebar",
				prefabName = "Item_Rebar",
				color = "#D3D3D3",
				description = "Start with rebar."
			},
			new ClimbingItemDef
			{
				title = "Holiday Piton",
				prefabName = "Item_Piton_Holiday",
				color = "#8DDDF5",
				description = "Start with holiday pitons."
			},
			new ClimbingItemDef
			{
				title = "Holiday Rebar",
				prefabName = "Item_Rebar_Holiday",
				color = "#8DDDF5",
				description = "Start with holiday rebar."
			},
			new ClimbingItemDef
			{
				title = "Holiday Rope Rebar",
				prefabName = "Item_RebarRope_Holiday",
				color = "#8DDDF5",
				description = "Start with holiday rope rebar."
			}
		};

		internal static void TryRun()
		{
			if (_done)
			{
				return;
			}
			Sprite val = ContortionIconCache.Get();
			bool flag = false;
			bool flag2 = true;
			ClimbingItemDef[] items = _items;
			for (int i = 0; i < items.Length; i++)
			{
				ClimbingItemDef climbingItemDef = items[i];
				string text = "cici_climb_" + climbingItemDef.prefabName;
				if (TrinketRegistry._registry.ContainsKey(text))
				{
					flag = true;
					continue;
				}
				Item_Object val2 = null;
				try
				{
					GameObject assetGameObject = CL_AssetManager.GetAssetGameObject(climbingItemDef.prefabName, "");
					val2 = (((Object)(object)assetGameObject != (Object)null) ? assetGameObject.GetComponent<Item_Object>() : null);
				}
				catch
				{
				}
				if ((Object)(object)val2 == (Object)null)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogInfo((object)("[AutoClimb] '" + climbingItemDef.prefabName + "' not yet loaded — skipping"));
					}
					flag2 = false;
					continue;
				}
				flag = true;
				Sprite icon = val ?? val2.itemData?.normalSprite;
				Item_Object ioRef = val2;
				string idCopy = text;
				TrinketRegistry.RegisterTrinket(text, climbingItemDef.title, climbingItemDef.description, "", 1, 0f, 0f, icon, delegate
				{
					TrinketRegistry.Entry value2;
					int num = ((!TrinketRegistry._registry.TryGetValue(idCopy, out value2)) ? 1 : Mathf.Max(1, value2.stackCount));
					List<Item_Object> list = new List<Item_Object>(num);
					for (int j = 0; j < num; j++)
					{
						list.Add(ioRef);
					}
					return list;
				});
				if (TrinketRegistry._registry.TryGetValue(text, out var value))
				{
					value.titleColor = climbingItemDef.color;
					value.maxStacks = 12;
					value.stackCount = 1;
					value.category = TrinketRegistry.Category.Other;
					value.bucket = TrinketRegistry.BucketFromColor(climbingItemDef.color);
					value.isFrameworkRegistered = true;
					value.isVanillaContent = true;
				}
			}
			if (flag2)
			{
				_done = true;
			}
			if (flag)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)$"[AutoClimb] Pass complete — allResolved={flag2}");
				}
			}
		}
	}
	public static class UnusedVanillaTrinketAutoRegistrar
	{
		private struct UnusedDef
		{
			public string title;

			public string prefabName;

			public string description;
		}

		private static bool _done;

		private static readonly UnusedDef[] _items = new UnusedDef[1]
		{
			new UnusedDef
			{
				title = "Calming Buddy",
				prefabName = "Item_Trinket_CalmingBuddy",
				description = "Start with the Calming Buddy trinket."
			}
		};

		internal static void TryRun()
		{
			if (_done)
			{
				return;
			}
			bool flag = false;
			bool flag2 = true;
			UnusedDef[] items = _items;
			for (int i = 0; i < items.Length; i++)
			{
				UnusedDef unusedDef = items[i];
				string text = "cici_unused_" + unusedDef.prefabName;
				if (TrinketRegistry._registry.ContainsKey(text))
				{
					flag = true;
					continue;
				}
				Item_Object val = null;
				try
				{
					GameObject assetGameObject = CL_AssetManager.GetAssetGameObject(unusedDef.prefabName, "");
					val = (((Object)(object)assetGameObject != (Object)null) ? assetGameObject.GetComponent<Item_Object>() : null);
				}
				catch
				{
				}
				if ((Object)(object)val == (Object)null)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogInfo((object)("[AutoUnused] '" + unusedDef.prefabName + "' not yet loaded — skipping"));
					}
					flag2 = false;
					continue;
				}
				flag = true;
				Sprite icon = val.itemData?.normalSprite;
				Item_Object ioRef = val;
				TrinketRegistry.RegisterTrinket(text, unusedDef.title, unusedDef.description, "", 1, 0f, 0f, icon, () => new List<Item_Object> { ioRef });
				if (TrinketRegistry._registry.TryGetValue(text, out var value))
				{
					value.pinToVanilla = true;
					value.isFrameworkRegistered = true;
					value.isVanillaContent = true;
				}
			}
			if (flag2)
			{
				_done = true;
			}
			if (flag)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)$"[AutoUnused] Pass complete — allResolved={flag2}");
				}
			}
		}
	}
	public static class MiscTrinketAutoRegistrar
	{
		private struct MiscDef
		{
			public string title;

			public string prefabName;

			public string color;

			public int tier;

			public string description;
		}

		private static bool _done;

		private const string LightGrey = "#D3D3D3";

		private const int MaxStacks = 12;

		private static readonly MiscDef[] _items = new MiscDef[7]
		{
			new MiscDef
			{
				title = "Flare",
				prefabName = "Item_Flaregun_Ammo",
				color = "#D3D3D3",
				tier = 0,
				description = "Start with flare(s)."
			},
			new MiscDef
			{
				title = "Gold Roach",
				prefabName = "Denizen_Roach_Gold",
				color = "#FFD700",
				tier = 0,
				description = "Start with gold roaches."
			},
			new MiscDef
			{
				title = "Platinum Roach",
				prefabName = "Denizen_Roach_Platinum",
				color = "#C0C0C0",
				tier = 0,
				description = "Start with platinum roaches."
			},
			new MiscDef
			{
				title = "Ruby Roach",
				prefabName = "Denizen_Roach_Flying_Ruby",
				color = "#ED4040",
				tier = 0,
				description = "Start with ruby roaches."
			},
			new MiscDef
			{
				title = "Tier 1 Floppy Disk",
				prefabName = "Item_Floppy_T1",
				color = "#D3D3D3",
				tier = 1,
				description = "Start with tier 1 floppy disks."
			},
			new MiscDef
			{
				title = "Tier 2 Floppy Disk",
				prefabName = "Item_Floppy_T2",
				color = "#662E1C",
				tier = 2,
				description = "Start with tier 2 floppy disks."
			},
			new MiscDef
			{
				title = "Tier 3 Floppy Disk",
				prefabName = "Item_Floppy_T3",
				color = "#493D06",
				tier = 3,
				description = "Start with tier 3 floppy disks."
			}
		};

		internal static void TryRun()
		{
			if (_done)
			{
				return;
			}
			Sprite val = ContortionIconCache.Get();
			bool flag = false;
			bool flag2 = true;
			MiscDef[] items = _items;
			for (int i = 0; i < items.Length; i++)
			{
				MiscDef miscDef = items[i];
				string text = "cici_misc_" + miscDef.prefabName;
				if (TrinketRegistry._registry.ContainsKey(text))
				{
					flag = true;
					continue;
				}
				Item_Object val2 = null;
				try
				{
					GameObject assetGameObject = CL_AssetManager.GetAssetGameObject(miscDef.prefabName, "");
					val2 = (((Object)(object)assetGameObject != (Object)null) ? assetGameObject.GetComponent<Item_Object>() : null);
				}
				catch
				{
				}
				if ((Object)(object)val2 == (Object)null)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogInfo((object)("[AutoMisc] '" + miscDef.prefabName + "' not yet loaded — skipping"));
					}
					flag2 = false;
					continue;
				}
				flag = true;
				Sprite icon = val ?? val2.itemData?.normalSprite;
				Item_Object ioRef = val2;
				string idCopy = text;
				TrinketRegistry.RegisterTrinket(text, miscDef.title, miscDef.description, "", 1, 0f, 0f, icon, delegate
				{
					TrinketRegistry.Entry value2;
					int num = ((!TrinketRegistry._registry.TryGetValue(idCopy, out value2)) ? 1 : Mathf.Max(1, value2.stackCount));
					List<Item_Object> list = new List<Item_Object>(num);
					for (int j = 0; j < num; j++)
					{
						list.Add(ioRef);
					}
					return list;
				});
				if (TrinketRegistry._registry.TryGetValue(text, out var value))
				{
					value.titleColor = miscDef.color;
					value.maxStacks = 12;
					value.stackCount = 1;
					value.category = TrinketRegistry.Category.Other;
					value.bucket = TrinketRegistry.BucketFromColor(miscDef.color);
					value.tier = miscDef.tier;
					value.isFrameworkRegistered = true;
					value.isVanillaContent = true;
				}
			}
			if (flag2)
			{
				_done = true;
			}
			if (flag)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)$"[AutoMisc] Pass complete — allResolved={flag2}");
				}
			}
		}
	}
	public static class ArtifactTrinketAutoRegistrar
	{
		private struct ArtifactDef
		{
			public string title;

			public string prefabName;

			public string color;

			public string description;

			public string flavor;
		}

		private static bool _done;

		private const string MutexGroup = "artifacts";

		private static readonly ArtifactDef[] _artifacts = new ArtifactDef[5]
		{
			new ArtifactDef
			{
				title = "Glove",
				prefabName = "Item_Artifact_EVAGlove",
				color = "#6DFDFD",
				description = "Start with the EVA Glove artifact.",
				flavor = ""
			},
			new ArtifactDef
			{
				title = "Remote",
				prefabName = "Item_Artifact_Remote",
				color = "#C0C0C0",
				description = "Start with the Remote artifact.",
				flavor = ""
			},
			new ArtifactDef
			{
				title = "Spear",
				prefabName = "Item_Artifact_Rebar_Return",
				color = "#ED4040",
				description = "Start with the Returning Spear artifact.",
				flavor = ""
			},
			new ArtifactDef
			{
				title = "Timepiece",
				prefabName = "Item_Artifact_Timepiece",
				color = "#8EF6DD",
				description = "Start with the Timepiece artifact.",
				flavor = ""
			},
			new ArtifactDef
			{
				title = "Translocator",
				prefabName = "Item_Artifact_Translocator",
				color = "#ED4040",
				description = "Start with the Translocator artifact.",
				flavor = ""
			}
		};

		internal static void TryRun()
		{
			if (_done)
			{
				return;
			}
			List<(ArtifactDef, Item_Object)> list = new List<(ArtifactDef, Item_Object)>();
			ArtifactDef[] artifacts = _artifacts;
			for (int i = 0; i < artifacts.Length; i++)
			{
				ArtifactDef item = artifacts[i];
				Item_Object val = null;
				try
				{
					GameObject assetGameObject = CL_AssetManager.GetAssetGameObject(item.prefabName, "");
					val = (((Object)(object)assetGameObject != (Object)null) ? assetGameObject.GetComponent<Item_Object>() : null);
				}
				catch
				{
				}
				if ((Object)(object)val == (Object)null)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogInfo((object)("[AutoArtifacts] '" + item.prefabName + "' not yet loaded — deferring"));
					}
					return;
				}
				list.Add((item, val));
			}
			Sprite val2 = ContortionIconCache.Get();
			List<string> list2 = new List<string>();
			foreach (var item4 in list)
			{
				ArtifactDef item2 = item4.Item1;
				Item_Object item3 = item4.Item2;
				string text = "cici_artifact_" + item2.prefabName;
				if (TrinketRegistry._registry.ContainsKey(text))
				{
					list2.Add(text);
					continue;
				}
				Sprite icon = val2 ?? item3.itemData?.normalSprite;
				Item_Object ioRef = item3;
				TrinketRegistry.RegisterTrinket(text, item2.title, item2.description, item2.flavor, 1, 0f, 0f, icon, () => new List<Item_Object> { ioRef });
				if (TrinketRegistry._registry.TryGetValue(text, out var value))
				{
					value.titleCo