Decompiled source of COTL API v0.2.2

plugins/io.github.xhayper.COTL_API/COTL_API.dll

Decompiled 3 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using COTL_API.CustomFollowerCommand;
using COTL_API.CustomInventory;
using COTL_API.CustomLocalization;
using COTL_API.CustomMission;
using COTL_API.CustomObjectives;
using COTL_API.CustomRelics;
using COTL_API.CustomSettings;
using COTL_API.CustomSettings.Elements;
using COTL_API.CustomSkins;
using COTL_API.CustomStructures;
using COTL_API.CustomTarotCard;
using COTL_API.CustomTasks;
using COTL_API.Debug;
using COTL_API.Guid;
using COTL_API.Helpers;
using COTL_API.Icons;
using COTL_API.Prefabs;
using COTL_API.Saves;
using DG.Tweening.Core;
using FMOD;
using FMODUnity;
using HarmonyLib;
using I2.Loc;
using Lamb.UI;
using Lamb.UI.Assets;
using Lamb.UI.BuildMenu;
using Lamb.UI.FollowerInteractionWheel;
using Lamb.UI.MainMenu;
using Lamb.UI.PauseMenu;
using Lamb.UI.RefineryMenu;
using Lamb.UI.Rituals;
using Lamb.UI.Settings;
using Lamb.UI.SettingsMenu;
using LeTai.Asset.TranslucentImage;
using MMBiomeGeneration;
using MMRoomGeneration;
using MMTools;
using Microsoft.CodeAnalysis;
using Microsoft.Win32.SafeHandles;
using MonoMod.Utils;
using Spine;
using Spine.Unity;
using Spine.Unity.AttachmentTools;
using TMPro;
using Unify;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Experimental.Rendering;
using UnityEngine.ProBuilder;
using UnityEngine.ResourceManagement;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.TextCore;
using UnityEngine.UI;
using src.Extensions;
using src.UI.InfoCards;
using src.UI.Menus;
using src.UINavigator;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.0", FrameworkDisplayName = ".NET Standard 2.0")]
[assembly: AssemblyCompany("COTL_API")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyDescription("A modding API for Cult of the Lamb")]
[assembly: AssemblyFileVersion("0.2.2.0")]
[assembly: AssemblyInformationalVersion("0.2.2+10fb6a3ad40a42a637aba98480379e7ed9053108")]
[assembly: AssemblyProduct("COTL_API")]
[assembly: AssemblyTitle("COTL_API")]
[assembly: AssemblyMetadata("RepositoryUrl", "https://github.com/xhayper/COTL_API")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.2.2.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsReadOnlyAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class IsUnmanagedAttribute : Attribute
	{
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace COTL_API
{
	public static class CustomType
	{
		public static Type? GetType(string nameSpace, string typeName)
		{
			string text = nameSpace + "." + typeName;
			Type type = Type.GetType(text);
			if (type != null)
			{
				return type;
			}
			if (text.Contains("."))
			{
				Assembly assembly = Assembly.Load(text.Substring(0, text.IndexOf('.')));
				if (assembly == null)
				{
					return null;
				}
				type = assembly.GetType(text);
				if (type != null)
				{
					return type;
				}
			}
			AssemblyName[] referencedAssemblies = Assembly.GetExecutingAssembly().GetReferencedAssemblies();
			for (int i = 0; i < referencedAssemblies.Length; i++)
			{
				Assembly assembly2 = Assembly.Load(referencedAssemblies[i]);
				if (!(assembly2 == null))
				{
					type = assembly2.GetType(text);
					if (type != null)
					{
						return type;
					}
				}
			}
			return null;
		}
	}
	[BepInPlugin("io.github.xhayper.COTL_API", "COTL_API", "0.2.2")]
	[HarmonyPatch]
	public class Plugin : BaseUnityPlugin
	{
		internal static Dropdown? SkinSettings;

		private readonly Harmony _harmony = new Harmony("io.github.xhayper.COTL_API");

		internal readonly ModdedSaveData<ApiData> APIData = new ModdedSaveData<ApiData>("io.github.xhayper.COTL_API")
		{
			LoadOrder = ModdedSaveLoadOrder.LOAD_AS_SOON_AS_POSSIBLE
		};

		internal readonly ModdedSaveData<ApiSlotData> APISlotData = new ModdedSaveData<ApiSlotData>("io.github.xhayper.COTL_API_slot");

		public readonly ModdedSaveData<ObjectDictionary> ModdedSettingsData = new ModdedSaveData<ObjectDictionary>("modded_settings")
		{
			LoadOrder = ModdedSaveLoadOrder.LOAD_AS_SOON_AS_POSSIBLE
		};

		internal bool DebugContentAdded;

		internal static ConfigEntry<bool> UnityDebug { get; private set; } = null;


		internal static Plugin? Instance { get; private set; }

		internal ManualLogSource Logger { get; private set; } = new ManualLogSource("COTL_API");


		internal string PluginPath { get; private set; } = "";


		private ConfigEntry<bool>? _debug { get; set; }

		public bool Debug => _debug?.Value ?? false;

		private ConfigEntry<bool>? _skipSplashScreen { get; set; }

		public bool SkipSplashScreen => _skipSplashScreen?.Value ?? false;

		private ConfigEntry<bool>? _dontSaveAchievement { get; set; }

		public bool DontSaveAchievement => _dontSaveAchievement?.Value ?? true;

		internal static bool Started { get; private set; }

		internal static ObjectDictionary? SettingsData
		{
			get
			{
				if (!((Object)(object)Instance != (Object)null))
				{
					return null;
				}
				return Instance.ModdedSettingsData.Data;
			}
		}

		internal static Dictionary<int, CustomObjective>? QuestData
		{
			get
			{
				if (!((Object)(object)Instance != (Object)null))
				{
					return null;
				}
				return Instance.APISlotData.Data?.QuestData;
			}
		}

		internal static ObjectDictionary? EnumData
		{
			get
			{
				if (!((Object)(object)Instance != (Object)null))
				{
					return null;
				}
				return Instance.APIData.Data?.EnumData;
			}
		}

		internal ITEM_TYPE DebugItem { get; private set; }

		internal ITEM_TYPE DebugItem2 { get; private set; }

		internal ITEM_TYPE DebugItem3 { get; private set; }

		internal ITEM_TYPE DebugItem4 { get; private set; }

		internal FollowerCommands DebugGiftFollowerCommand { get; private set; }

		internal RelicType DebugRelic { get; private set; }

		internal static event Action OnStart;

		private void Awake()
		{
			Instance = this;
			Logger = ((BaseUnityPlugin)this).Logger;
			PluginPath = Path.GetDirectoryName(((BaseUnityPlugin)this).Info.Location) ?? string.Empty;
			ModdedSaveManager.RegisterModdedSave(ModdedSettingsData);
			ModdedSaveManager.RegisterModdedSave(APIData);
			ModdedSaveManager.RegisterModdedSave(APISlotData);
			RunSavePatch();
			_skipSplashScreen = ((BaseUnityPlugin)this).Config.Bind<bool>("Miscellaneous", "Skip Splash Screen", false, "Should we skip the splash screen or not?");
			_dontSaveAchievement = ((BaseUnityPlugin)this).Config.Bind<bool>("Miscellaneous", "Dont Save Achievement", true, "Should we save the achievement to the cloud or not? (Cloud being Steam / GOG / PSN)");
			_debug = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "API Debug", false, "API debug mode. Will add debug content to your game for testing. Not recommended for normal play.");
			UnityDebug = ((BaseUnityPlugin)this).Config.Bind<bool>("Debug", "Unity Debug Logging", true, "Unity debug logging. Helpful to filter out unrelated entries during testing.");
			UnityDebug.SettingChanged += delegate
			{
				Debug.unityLogger.logEnabled = UnityDebug.Value;
			};
			CustomSkinManager.AddPlayerSkin(new OverridingPlayerSkin("Goat", S1));
			CustomSkinManager.AddPlayerSkin(new OverridingPlayerSkin("Owl", S2));
			CustomSkinManager.AddPlayerSkin(new OverridingPlayerSkin("Snake", S3));
			SkinSettings = CustomSettingsManager.AddSavedDropdown("API", "io.github.xhayper.COTL_API", "Lamb Skin", "Default", new string[1] { "Default" }.Concat(CustomSkinManager.CustomPlayerSkins.Keys).ToArray(), delegate(int i)
			{
				if (0 >= i)
				{
					CustomSkinManager.ResetPlayerSkin();
				}
				else
				{
					CustomSkinManager.SetPlayerSkinOverride(CustomSkinManager.CustomPlayerSkins.Values.ElementAt(i - 1));
				}
			});
			CustomSettingsManager.AddBepInExConfig("API", "Skip Splash Screen", _skipSplashScreen);
			CustomSettingsManager.AddBepInExConfig("API", "Don't Save Achievement", _dontSaveAchievement, delegate(bool isActivated)
			{
				if (!isActivated)
				{
					AchievementsWrapper.LoadAchievementData();
					AchievementsWrapper.compareAchievements();
				}
			});
			CustomSettingsManager.AddBepInExConfig("API", "Debug Mode", _debug, delegate(bool isActivated)
			{
				if (!isActivated)
				{
					if (!(SkinSettings?.Value != "Debug Skin"))
					{
						SkinSettings.Value = "Default";
						CustomSkinManager.ResetPlayerSkin();
					}
				}
				else if (!DebugContentAdded)
				{
					AddDebugContent();
				}
			});
			CustomSettingsManager.AddBepInExConfig("API", "Unity Debug Logging", UnityDebug);
			if (Debug)
			{
				AddDebugContent();
			}
			LogHelper.LogInfo("COTL_API loaded!");
			static Skin S1()
			{
				return ((SkeletonRenderer)PlayerFarming.Instance.Spine).Skeleton.Data.FindSkin("Goat");
			}
			static Skin S2()
			{
				return ((SkeletonRenderer)PlayerFarming.Instance.Spine).Skeleton.Data.FindSkin("Owl");
			}
			static Skin S3()
			{
				return ((SkeletonRenderer)PlayerFarming.Instance.Spine).Skeleton.Data.FindSkin("Snake");
			}
		}

		private void Start()
		{
			Plugin.OnStart();
			Started = true;
		}

		public void Update()
		{
			if (Debug && Input.GetKeyDown((KeyCode)282))
			{
				List<Health> list = new List<Health>(Health.team2);
				GameObject entityObject = GameObject.FindWithTag("Player");
				CollectionExtensions.DoIf<Health>((IEnumerable<Health>)list, (Func<Health, bool>)((Health x) => (Object)(object)x != (Object)null), (Action<Health>)delegate(Health x)
				{
					//IL_0012: Unknown result type (might be due to invalid IL or missing references)
					x.DealDamage(999999f, (GameObject)null, entityObject.transform.position, false, (AttackTypes)0, false, (AttackFlags)0);
				});
			}
		}

		private void OnEnable()
		{
			_harmony.PatchAll(Assembly.GetExecutingAssembly());
			LogHelper.LogInfo($"{_harmony.GetPatchedMethods().Count()} harmony patches applied!");
		}

		private void OnDisable()
		{
			_harmony.UnpatchSelf();
			LogHelper.LogInfo("COTL_API unloaded!");
		}

		private void RunSavePatch()
		{
			SaveAndLoad.OnLoadComplete = (Action)Delegate.Combine(SaveAndLoad.OnLoadComplete, (Action)delegate
			{
				LogHelper.LogDebug("Loading Modded Save Data with LoadOrder=ModdedSaveLoadOrder.LOAD_AFTER_SAVE_START.");
				foreach (BaseModdedSaveData item in ModdedSaveManager.ModdedSaveDataList.Values.Where((BaseModdedSaveData save) => save.LoadOrder == ModdedSaveLoadOrder.LOAD_AFTER_SAVE_START))
				{
					item.Load(SaveAndLoad.SAVE_SLOT);
				}
				LogHelper.LogDebug("Re-adding any custom quests from the players existing objectives.");
				Dictionary<int, CustomObjective> dictionary = new Dictionary<int, CustomObjective>();
				if (QuestData == null)
				{
					return;
				}
				foreach (KeyValuePair<int, CustomObjective> objective in QuestData)
				{
					if (DataManager.instance.Objectives.Exists((ObjectivesData a) => a.ID == objective.Key))
					{
						dictionary.Add(objective.Key, objective.Value);
					}
					else if (Quests.QuestsAll.Exists((ObjectivesData a) => a.ID == objective.Key))
					{
						dictionary.Add(objective.Key, objective.Value);
					}
				}
				Extensions.AddRange<int, CustomObjective>(CustomObjectiveManager.CustomObjectiveList, dictionary);
				LogHelper.LogDebug("Added custom quests to Plugin.Instance.APIQuestData.Data.QuestData.");
				foreach (KeyValuePair<int, CustomObjective> customObjective in CustomObjectiveManager.CustomObjectiveList)
				{
					Extensions.TryAdd(QuestData, customObjective.Key, customObjective.Value);
				}
			});
			COTLDataReadWriter<SettingsData> readWriter = Singleton<SettingsManager>.Instance._readWriter;
			((MMDataReadWriterBase<SettingsData>)(object)readWriter).OnReadCompleted = (Action<SettingsData>)Delegate.Combine(((MMDataReadWriterBase<SettingsData>)(object)readWriter).OnReadCompleted, (Action<SettingsData>)delegate
			{
				if (!LocalizationManager.HasLanguage(SettingsManager.Settings.Game.Language, true, true, true))
				{
					SettingsManager.Settings.Game.Language = "English";
					LocalizationManager.CurrentLanguage = "English";
					if (TwitchAuthentication.IsAuthenticated)
					{
						TwitchRequest.SendEBSData();
					}
					LocalizationManager.LocalizeAll(true);
				}
			});
			SaveAndLoad.OnLoadComplete = (Action)Delegate.Combine(SaveAndLoad.OnLoadComplete, (Action)delegate
			{
				if (DataManager.Instance == null)
				{
					return;
				}
				foreach (QuestHistoryData item2 in DataManager.Instance.CompletedQuestsHistorys.Where((QuestHistoryData a) => a.QuestIndex >= Quests.QuestsAll.Count))
				{
					if (Debug)
					{
						LogHelper.LogDebug("Found quests in history with an index higher than total quests (user may have removed mods that add quests), resetting to maximum possible.");
					}
					item2.QuestIndex = Quests.QuestsAll.Count - 1;
				}
			});
		}

		private void AddDebugContent()
		{
			//IL_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: 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_00d3: 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_0247: Unknown result type (might be due to invalid IL or missing references)
			if (!DebugContentAdded)
			{
				CustomLocalizationManager.LoadLocalization("English", Path.Combine(PluginPath, "Assets", "English-Debug.language"));
				CustomSkinManager.AddFollowerSkin(new DebugFollowerSkin());
				CustomSkinManager.AddPlayerSkin(new DebugPlayerSkin());
				CustomFollowerCommandManager.Add(new DebugFollowerCommand());
				CustomFollowerCommandManager.Add(new DebugFollowerCommandClass2());
				CustomFollowerCommandManager.Add(new DebugFollowerCommandClass3());
				DebugGiftFollowerCommand = CustomFollowerCommandManager.Add(new DebugGiftFollowerCommand());
				DebugItem = CustomItemManager.Add(new DebugItemClass());
				DebugItem2 = CustomItemManager.Add(new DebugItemClass2());
				DebugItem3 = CustomItemManager.Add(new DebugItemClass3());
				DebugItem4 = CustomItemManager.Add(new DebugItemClass4());
				CustomStructureManager.Add(new DebugStructure());
				CustomStructureManager.Add(new DebugStructure2());
				CustomStructureManager.Add(new DebugStructure3());
				CustomTarotCardManager.Add(new DebugTarotCard());
				CustomTaskManager.Add(new DebugTask());
				CustomObjectiveManager.BedRest("Test").InitialQuestText = "This is my custom quest text for this objective.";
				CustomSettingsManager.AddDropdown("Debug", "Dropdown", "Option 1", new string[3] { "Option 1", "Option 2", "Option 3" }, delegate(int i)
				{
					LogHelper.LogDebug($"Dropdown selected {i}");
				});
				CustomSettingsManager.AddKeyboardShortcutDropdown("Debug", "Keyboard Shortcut", (KeyCode)0, delegate(KeyboardShortcut i)
				{
					//IL_0005: Unknown result type (might be due to invalid IL or missing references)
					LogHelper.LogDebug($"Keyboard Shortcut selected {i}");
				});
				CustomSettingsManager.AddHorizontalSelector("Debug", "Horizontal Selector", "Option 1", new string[3] { "Option 1", "Option 2", "Option 3" }, delegate(int i)
				{
					LogHelper.LogDebug($"Horizontal Selector selected {i}");
				});
				CustomSettingsManager.AddSlider("Debug", "Slider", 0f, -100f, 100f, 1, (ValueDisplayFormat)1, delegate(float i)
				{
					LogHelper.LogDebug($"Slider value: {i}");
				});
				CustomSettingsManager.AddToggle("Debug", "Toggle", value: true, delegate(bool i)
				{
					LogHelper.LogDebug($"Toggled: {i}");
				});
				DebugRelic = CustomRelicManager.Add(ScriptableObject.CreateInstance<DebugRelicClass>());
				LogHelper.LogDebug("Debug mode enabled!");
				DebugContentAdded = true;
			}
		}

		static Plugin()
		{
			Plugin.OnStart = delegate
			{
			};
		}
	}
	public static class MyPluginInfo
	{
		public const string PLUGIN_GUID = "io.github.xhayper.COTL_API";

		public const string PLUGIN_NAME = "COTL_API";

		public const string PLUGIN_VERSION = "0.2.2";
	}
}
namespace COTL_API.Sounds
{
	internal class ChannelWrapper
	{
		private readonly SoundWrapper soundWrapper;

		private Channel channel;

		public float VolumeMultiplier = 1f;

		public string ID { get; }

		public ChannelWrapper(string id, in SoundWrapper sound, bool loop = false)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			channel = default(Channel);
			ID = id;
			soundWrapper = sound;
		}

		public RESULT Play()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: 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_002c: Unknown result type (might be due to invalid IL or missing references)
			System coreSystem = RuntimeManager.CoreSystem;
			RESULT val = ((System)(ref coreSystem)).playSound(soundWrapper.GetSound(), default(ChannelGroup), false, ref channel);
			if ((int)val == 0)
			{
				return val;
			}
			val.IfErrorPrintWith("Play -- SoundHandler instance id: " + ID);
			return val;
		}

		public void SetVolume(float a)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			((Channel)(ref channel)).setVolume(a * VolumeMultiplier).IfErrorPrintWith("SetVolume -- SoundHandler instance id: " + ID);
		}

		public void SetMultiplier(float a)
		{
			VolumeMultiplier = a;
		}

		public void Stop()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			((Channel)(ref channel)).stop().IfErrorPrintWith("Stop -- SoundHandler instance id: " + ID);
		}

		public bool IsPlaying()
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			bool result = default(bool);
			((Channel)(ref channel)).isPlaying(ref result).IfErrorPrintWith("isPlaying -- SoundHandler instance id: " + ID);
			return result;
		}

		public bool IsPaused()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (!IsPlaying())
			{
				return false;
			}
			bool result = default(bool);
			((Channel)(ref channel)).getPaused(ref result).IfErrorPrintWith("isPaused -- SoundHandler instance id: " + ID);
			return result;
		}

		public void Pause(bool pause)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			if (IsPlaying())
			{
				((Channel)(ref channel)).setPaused(pause).IfErrorPrintWith("Pause -- SoundHandler instance id: " + ID);
			}
		}

		public void SetReverb(bool active, float a)
		{
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp(a, 0f, 1f) * (float)Convert.ToInt32(active);
			((Channel)(ref channel)).setReverbProperties(0, num).IfErrorPrintWith("SetReverb -- SoundHandler instance id: " + ID);
		}

		public void SetLowPass(float a)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			a = Mathf.Clamp(a, 0f, 1f);
			((Channel)(ref channel)).setLowPassGain(a).IfErrorPrintWith("SetLowPass -- SoundHandler instance id: " + ID);
		}
	}
	public class SoundLoader : MonoBehaviour
	{
		internal static readonly List<SoundLoader> InstanceList = new List<SoundLoader>();

		private readonly List<ChannelWrapper> _channelList = new List<ChannelWrapper>();

		private readonly Dictionary<string, SoundWrapper> _soundCache = new Dictionary<string, SoundWrapper>();

		private void OnDestroy()
		{
			InstanceList.Remove(this);
			StopAll();
		}

		public string CreateSound(string fileName, string? name = null)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			SoundWrapper value = new SoundWrapper(SoundUtils.MakeSound(fileName));
			if (name == null)
			{
				name = fileName;
			}
			_soundCache.Add(name, value);
			return name;
		}

		public void PlaySfx(string name)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			if (!_soundCache.ContainsKey(name))
			{
				LogHelper.LogError("Error playing sound " + name + ": Sound doesn't exist!");
			}
			SoundUtils.PlayOneShot(_soundCache[name]);
		}

		public void PlayMusic(string name)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			if (!_soundCache.ContainsKey(name))
			{
				LogHelper.LogError("Error playing sound " + name + ": Sound doesn't exist!");
			}
			SoundWrapper sound = _soundCache[name];
			sound.ChangeLoopMode((MODE)2);
			ChannelWrapper channelWrapper = new ChannelWrapper(name, in sound);
			RESULT val = channelWrapper.Play();
			channelWrapper.SetVolume(SoundUtils.MusicVolume);
			if ((int)val == 0)
			{
				_channelList.Add(channelWrapper);
			}
		}

		public void CreateAndPlayMusic(string fileName, string? name = null)
		{
			string name2 = CreateSound(fileName, name);
			PlayMusic(name2);
		}

		public void CreateAndPlaySfx(string fileName, string? name = null)
		{
			string name2 = CreateSound(fileName, name);
			PlaySfx(name2);
		}

		public void StopAll()
		{
			_channelList.ForEach(delegate(ChannelWrapper x)
			{
				x.Stop();
			});
			_channelList.Clear();
		}

		internal void SyncAllVolume()
		{
			_channelList.ForEach(delegate(ChannelWrapper x)
			{
				x.SetVolume(SoundUtils.MusicVolume);
			});
		}

		public void ClearSounds()
		{
			_soundCache.Clear();
		}

		private ChannelWrapper? GetHandlerByID(string id)
		{
			string id2 = id;
			return _channelList.FirstOrDefault((ChannelWrapper x) => x.ID == id2);
		}

		internal void SyncVolume(string id)
		{
			GetHandlerByID(id)?.SetVolume(SoundUtils.MusicVolume);
		}

		public void VolumeMultiplier(string id, float mul)
		{
			ChannelWrapper? handlerByID = GetHandlerByID(id);
			handlerByID?.SetMultiplier(mul);
			handlerByID?.SetVolume(SoundUtils.MusicVolume);
		}

		public void Stop(string name)
		{
			ChannelWrapper handlerByID = GetHandlerByID(name);
			handlerByID?.Stop();
			if (handlerByID != null)
			{
				_channelList.Remove(handlerByID);
			}
		}

		public void Pause(string name, bool pause)
		{
			GetHandlerByID(name)?.Pause(pause);
		}

		public bool IsPlaying(string name)
		{
			return GetHandlerByID(name)?.IsPlaying() ?? false;
		}

		public bool IsPaused(string name)
		{
			return GetHandlerByID(name)?.IsPaused() ?? false;
		}
	}
	public static class SoundLoaderExtensions
	{
		public static SoundLoader AddSoundLoader(this GameObject obj)
		{
			SoundLoader soundLoader = obj.AddComponent<SoundLoader>();
			SoundLoader.InstanceList.Add(soundLoader);
			return soundLoader;
		}
	}
	public enum VolumeCategory
	{
		MASTER,
		MUSIC,
		SFX,
		VO
	}
	public static class SoundUtils
	{
		public static float MasterVolume => SettingsManager.Settings.Audio.MasterVolume;

		public static float MusicVolume => SettingsManager.Settings.Audio.MusicVolume * MasterVolume;

		public static float SfxVolume => SettingsManager.Settings.Audio.SFXVolume * MasterVolume;

		public static float VoVolume => SettingsManager.Settings.Audio.VOVolume * MasterVolume;

		internal static RESULT SyncVolume(this Channel channel, VolumeCategory volumeCategory = VolumeCategory.MASTER)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			return ((Channel)(ref channel)).setVolume(GetVolume(volumeCategory));
		}

		internal static float GetVolume(VolumeCategory x)
		{
			return x switch
			{
				VolumeCategory.MUSIC => MusicVolume, 
				VolumeCategory.SFX => SfxVolume, 
				VolumeCategory.VO => VoVolume, 
				_ => MasterVolume, 
			};
		}

		internal static void IfErrorPrintWith(this RESULT result, string where)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if ((int)result != 0)
			{
				LogHelper.LogError($"Sound Error: {result} caught at {where}");
			}
		}

		internal static string? GetPath(string fileName)
		{
			string obj = (Path.IsPathRooted(fileName) ? fileName : Directory.GetFiles(Paths.PluginPath, fileName, SearchOption.AllDirectories).FirstOrDefault());
			if (obj == null)
			{
				LogHelper.LogError("Error: Couldn't find \"" + fileName + "\"");
			}
			return obj;
		}

		internal static Sound MakeSound(string fileName, bool loop = false)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			string path = GetPath(fileName);
			if (path == null)
			{
				return default(Sound);
			}
			System coreSystem = RuntimeManager.CoreSystem;
			MODE val = (MODE)((!loop) ? 1 : 2);
			Sound result = default(Sound);
			RESULT val2 = ((System)(ref coreSystem)).createSound(path, val, ref result);
			if ((int)val2 == 0)
			{
				return result;
			}
			LogHelper.LogError("Error making sound from file " + fileName + "!");
			val2.IfErrorPrintWith("MakeSound() -- fileName: " + fileName);
			return default(Sound);
		}

		internal static RESULT PlayOneShot(SoundWrapper soundHandle, VolumeCategory volume = VolumeCategory.SFX)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			System coreSystem = RuntimeManager.CoreSystem;
			soundHandle.ChangeLoopMode((MODE)1);
			Channel channel = default(Channel);
			RESULT result = ((System)(ref coreSystem)).playSound(soundHandle.GetSound(), default(ChannelGroup), false, ref channel);
			channel.SyncVolume(volume);
			return result;
		}

		internal static RESULT PlayOneShot(string path, VolumeCategory volume = VolumeCategory.SFX)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			return PlayOneShot(new SoundWrapper(MakeSound(path)), volume);
		}
	}
	internal class SoundWrapper : SafeHandleZeroOrMinusOneIsInvalid
	{
		private readonly Sound? sound;

		public SoundWrapper(Sound sound)
			: base(ownsHandle: true)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			SetHandle(sound.handle);
			this.sound = sound;
		}

		public Sound GetSound()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return sound.GetValueOrDefault();
		}

		public void ChangeLoopMode(MODE mode)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			ref readonly Sound? reference = ref sound;
			if (reference.HasValue)
			{
				Sound valueOrDefault = reference.GetValueOrDefault();
				((Sound)(ref valueOrDefault)).setMode(mode);
			}
		}

		[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
		protected override bool ReleaseHandle()
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			ref readonly Sound? reference = ref sound;
			if (reference.HasValue)
			{
				Sound valueOrDefault = reference.GetValueOrDefault();
				((Sound)(ref valueOrDefault)).release();
			}
			return true;
		}
	}
}
namespace COTL_API.Sounds.Patches
{
	[HarmonyPatch]
	public static class SoundSyncPatches
	{
		[HarmonyPatch(typeof(AudioSettings), "OnMasterVolumeChanged")]
		[HarmonyPostfix]
		private static void SyncMaster()
		{
			SoundLoader.InstanceList.ForEach(delegate(SoundLoader x)
			{
				x.SyncAllVolume();
			});
		}

		[HarmonyPatch(typeof(AudioSettings), "OnMusicVolumeChanged")]
		[HarmonyPostfix]
		private static void SyncMusic()
		{
			SoundLoader.InstanceList.ForEach(delegate(SoundLoader x)
			{
				x.SyncAllVolume();
			});
		}
	}
}
namespace COTL_API.Prefabs
{
	[HarmonyPatch]
	public static class CustomPrefabManager
	{
		private static string? _pathOverride;

		internal static Dictionary<string, CustomStructure> PrefabStrings { get; } = new Dictionary<string, CustomStructure>();


		public static string GetOrCreateBuildingPrefab(CustomStructure structure)
		{
			string text = "CustomBuildingPrefab_" + structure.InternalName;
			string key = "Assets/" + text + ".prefab";
			if (PrefabStrings.ContainsValue(structure))
			{
				return text;
			}
			PrefabStrings.Add(text, structure);
			PrefabStrings.Add(key, structure);
			return text;
		}

		private static void CreateBuildingPrefabOverride(string name, ref AsyncOperationHandle<GameObject> handle)
		{
			string name2 = name;
			if (!PrefabStrings.ContainsKey(name2))
			{
				CustomStructure structureByPrefabName = CustomStructureManager.GetStructureByPrefabName(name2);
				if (structureByPrefabName == null)
				{
					LogHelper.LogWarning("Structure " + name2 + " not found in CustomStructureManager");
					return;
				}
				GetOrCreateBuildingPrefab(structureByPrefabName);
			}
			Sprite sprite = PrefabStrings[name2].Sprite;
			handle.Completed += delegate(AsyncOperationHandle<GameObject> obj)
			{
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				//IL_002d: 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_0052: Unknown result type (might be due to invalid IL or missing references)
				SpriteRenderer componentInChildren = obj.Result.GetComponentInChildren<SpriteRenderer>();
				obj.Result.GetComponentInChildren<Structure>().Type = PrefabStrings[name2].StructureType;
				Sprite sprite2 = Sprite.Create(sprite.texture, sprite.rect, new Vector2(0.5f, 0f));
				componentInChildren.sprite = sprite2;
				((Object)obj.Result).name = name2 + " (Custom Structure)";
			};
		}

		[HarmonyWrapSafe]
		[HarmonyPatch(typeof(AddressablesImpl), "InstantiateAsync", new Type[]
		{
			typeof(object),
			typeof(InstantiationParameters),
			typeof(bool)
		})]
		[HarmonyPrefix]
		private static void Addressables_InstantiateAsync(ref object key)
		{
			if (key is string text && text.Contains("CustomBuildingPrefab_"))
			{
				if (!CustomStructureManager.CustomStructureExists(text))
				{
					LogHelper.LogWarning("Structure attempting to be loaded no longer exists. Path: " + text);
					_pathOverride = null;
					key = "Assets/Prefabs/Structures/Other/Rubble.prefab";
				}
				else
				{
					_pathOverride = text;
					key = "Assets/Prefabs/Structures/Buildings/Decoration Wreath Stick.prefab";
				}
			}
		}

		[HarmonyWrapSafe]
		[HarmonyPatch(typeof(ResourceManager), "ProvideInstance")]
		[HarmonyPostfix]
		private static void ResourceManager_ProvideInstance(ref AsyncOperationHandle<GameObject> __result)
		{
			if (_pathOverride != null)
			{
				CreateBuildingPrefabOverride(_pathOverride, ref __result);
				_pathOverride = null;
			}
		}

		public static GameObject CreatePlacementObjectFor(CustomStructure structure)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			GameObject placementObject = TypeAndPlacementObjects.GetByType((TYPES)2).PlacementObject;
			PlacementObject component = placementObject.GetComponent<PlacementObject>();
			component.ToBuildAsset = structure.PrefabPath;
			component.StructureType = structure.StructureType;
			component.Bounds = structure.Bounds;
			return placementObject;
		}
	}
}
namespace COTL_API.Patches
{
	[HarmonyPatch]
	public static class AchievementsWrapperPatches
	{
		[HarmonyPatch(typeof(AchievementsWrapper), "UnlockAchievement")]
		[HarmonyPrefix]
		private static bool AchievementsWrapper_UnlockAchievement(ref Achievement achievementId)
		{
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Plugin.Instance == (Object)null || !Plugin.Instance.DontSaveAchievement)
			{
				return true;
			}
			if (AchievementsWrapper.unlockedAchievements.Contains(achievementId.id))
			{
				return false;
			}
			AchievementsWrapper.unlockedAchievements.Add(achievementId.id);
			AchievementsWrapper.OnAchievementUnlocked?.Invoke(achievementId.label);
			if (achievementId == Achievements.Instance.Lookup("platinum"))
			{
				return false;
			}
			AchievementsWrapper.compareAchievements();
			return false;
		}

		[HarmonyPatch(typeof(AchievementsWrapper), "GetAchievementProgress")]
		[HarmonyPrefix]
		private static bool AchievementsWrapper_GetAchievementProgress(ref List<AchievementProgress> result)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: 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)
			if ((Object)(object)Plugin.Instance == (Object)null || !Plugin.Instance.DontSaveAchievement)
			{
				return true;
			}
			if (result == null || result.Count == 0)
			{
				return false;
			}
			foreach (AchievementProgress item in result.Where((AchievementProgress achievementProgress) => achievementProgress.progress >= 100 && !AchievementsWrapper.unlockedAchievements.Contains(achievementProgress.id)))
			{
				AchievementsWrapper.unlockedAchievements.Add(item.id);
				AchievementsWrapper.OnAchievementUnlocked?.Invoke(item.name);
			}
			return false;
		}

		[HarmonyPatch(typeof(AchievementsWrapper), "UnlockPlatinum")]
		[HarmonyPrefix]
		private static bool AchievementsWrapper_UnlockPlatinum()
		{
			if (!((Object)(object)Plugin.Instance == (Object)null))
			{
				return !Plugin.Instance.DontSaveAchievement;
			}
			return true;
		}
	}
	[HarmonyPatch]
	public static class IconPatcher
	{
		[HarmonyPatch(typeof(TMP_SpriteAsset), "SearchForSpriteByHashCode")]
		[HarmonyPrefix]
		private static bool TMP_SpriteAsset_SearchForSpriteByHashCode(TMP_SpriteAsset spriteAsset, int hashCode, bool includeFallbacks, ref int spriteIndex, ref TMP_SpriteAsset __result)
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: 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)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)spriteAsset == (Object)null)
			{
				return true;
			}
			Rect rect;
			GlyphMetrics iconMetrics = default(GlyphMetrics);
			foreach (CustomInventoryItem value in CustomItemManager.CustomItemList.Values)
			{
				string text = "icon_ITEM_" + value.ModPrefix + "." + value.InternalName;
				if (hashCode == COTL_API.Helpers.HashCode.GetValueHashCode(text))
				{
					spriteIndex = 0;
					Sprite inventoryIcon = value.InventoryIcon;
					rect = inventoryIcon.rect;
					float width = ((Rect)(ref rect)).width;
					rect = inventoryIcon.rect;
					float height = ((Rect)(ref rect)).height;
					rect = inventoryIcon.rect;
					float num = ((Rect)(ref rect)).height * 0.75f;
					rect = inventoryIcon.rect;
					((GlyphMetrics)(ref iconMetrics))..ctor(width, height, 0f, num, ((Rect)(ref rect)).width);
					__result = CustomIconManager.GetIcon(inventoryIcon, text, iconMetrics);
					return false;
				}
			}
			GlyphMetrics iconMetrics2 = default(GlyphMetrics);
			foreach (COTL_API.CustomFollowerCommand.CustomFollowerCommand value2 in CustomFollowerCommandManager.CustomFollowerCommandList.Values)
			{
				string text2 = "icon_FCOMMAND_" + value2.ModPrefix + "." + value2.InternalName;
				if (hashCode == COTL_API.Helpers.HashCode.GetValueHashCode(text2))
				{
					spriteIndex = 0;
					Sprite commandIcon = value2.CommandIcon;
					rect = commandIcon.rect;
					float width2 = ((Rect)(ref rect)).width;
					rect = commandIcon.rect;
					float height2 = ((Rect)(ref rect)).height;
					rect = commandIcon.rect;
					float height3 = ((Rect)(ref rect)).height;
					rect = commandIcon.rect;
					((GlyphMetrics)(ref iconMetrics2))..ctor(width2, height2, 0f, height3, ((Rect)(ref rect)).width);
					__result = CustomIconManager.GetIcon(commandIcon, text2, iconMetrics2);
					return false;
				}
			}
			return true;
		}
	}
	[HarmonyPatch]
	public static class LoadMainMenuPatches
	{
		private static IEnumerator GetEmptyEnumerator()
		{
			yield break;
		}

		[HarmonyPatch(typeof(LoadMainMenu), "RunSplashScreens")]
		[HarmonyPrefix]
		private static bool LoadMainMenu_RunSplashScreens(ref IEnumerator __result)
		{
			if ((Object)(object)Plugin.Instance != (Object)null && !Plugin.Instance.SkipSplashScreen)
			{
				return true;
			}
			__result = GetEmptyEnumerator();
			MMTransition.Play((TransitionType)0, (Effect)0, "Main Menu", 1f, "", (Action)null);
			return false;
		}
	}
	[HarmonyPatch]
	public static class SettingsPatches
	{
		[HarmonyPatch(typeof(MMHorizontalSelector), "UpdateContent")]
		[HarmonyPrefix]
		private static void MMHorizontalSelector_UpdateContent(MMHorizontalSelector __instance, string[] newContent)
		{
			if (__instance._contentIndex >= newContent.Length)
			{
				__instance._contentIndex = 0;
			}
		}

		[HarmonyPatch(typeof(LoadMenu), "OnTryLoadSaveSlot")]
		[HarmonyPostfix]
		private static void LoadMenu_OnTryLoadSaveSlot()
		{
			string text = Plugin.SkinSettings?.Value;
			if ((text != null && !(text == "Default")) || 1 == 0)
			{
				if (CustomSkinManager.CustomPlayerSkins.TryGetValue(Plugin.SkinSettings.Value, out CustomPlayerSkin value))
				{
					CustomSkinManager.SetPlayerSkinOverride(value);
				}
				else
				{
					Plugin.SkinSettings.Value = "Default";
				}
			}
		}
	}
	[HarmonyPatch]
	public static class UIFollowerInteractionWheelOverlayControllerPatches
	{
		[HarmonyPatch(typeof(UIFollowerInteractionWheelOverlayController), "MakeChoice", new Type[] { typeof(UIFollowerWheelInteractionItem) })]
		[HarmonyWrapSafe]
		public static class MakeChoice
		{
			[HarmonyPrefix]
			public static bool Prefix(ref UIFollowerWheelInteractionItem item, ref bool __state)
			{
				if (item.CommandItem is COTL_API.CustomFollowerCommand.CustomFollowerCommand)
				{
					List<CommandItem> subCommands = item.CommandItem.SubCommands;
					if (subCommands != null && subCommands.Count > 0)
					{
						LogHelper.LogDebug("Custom command with sub commands, not letting normal method run.");
						__state = true;
						return false;
					}
				}
				if ((Object)(object)Plugin.Instance != (Object)null && Plugin.Instance.Debug)
				{
					LogHelper.LogDebug("Not a custom command or doesnt have sub-commands, letting normal method run.");
				}
				__state = false;
				return true;
			}

			[HarmonyPostfix]
			public static void Postfix(ref UIFollowerInteractionWheelOverlayController __instance, ref UIFollowerWheelInteractionItem item, ref Follower ____follower, ref Stack<List<CommandItem>> ____commandStack, ref Stack<FollowerCommands> ____commandHistory, ref List<CommandItem> ____rootCommandItems, ref bool __state)
			{
				//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c9: Invalid comparison between Unknown and I4
				//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
				//IL_0069: Unknown result type (might be due to invalid IL or missing references)
				if (!__state)
				{
					return;
				}
				if ((Object)(object)Plugin.Instance != (Object)null && Plugin.Instance.Debug)
				{
					LogHelper.LogDebug("Custom command original method skipped, this is from the postfix.");
				}
				List<CommandItem> subCommands = item.CommandItem.SubCommands;
				if (subCommands != null && subCommands.Count > 0)
				{
					if (item.CommandItem.IsAvailable(____follower))
					{
						____commandStack.Push(____rootCommandItems);
						____commandHistory.Push(item.CommandItem.Command);
						____rootCommandItems = item.CommandItem.SubCommands;
						((MonoBehaviour)__instance).StartCoroutine(__instance.NextCategory(____rootCommandItems));
					}
					else
					{
						if ((Object)(object)Plugin.Instance != (Object)null && Plugin.Instance.Debug)
						{
							LogHelper.LogDebug("User pressed select on a greyed out sub command, closing menu and aborting choice.");
						}
						((UIMenuBase)__instance).OnCancelButtonInput();
					}
				}
				else if ((int)item.FollowerCommand == 41)
				{
					((UIMenuBase)__instance).OnCancelButtonInput();
				}
				else
				{
					((UIMenuBase)__instance).Hide(false);
					____commandHistory.Push(item.CommandItem.Command);
					((UIRadialMenuBase<UIFollowerWheelInteractionItem, FollowerCommands[]>)(object)__instance).OnItemChosen?.Invoke(____commandHistory.ToArray());
				}
			}
		}
	}
}
namespace COTL_API.Icons
{
	internal static class CustomIconManager
	{
		private static Dictionary<Sprite, TMP_SpriteAsset> Icons { get; } = new Dictionary<Sprite, TMP_SpriteAsset>();


		internal static TMP_SpriteAsset GetIcon(Sprite icon, string name, GlyphMetrics iconMetrics)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			if (Icons.TryGetValue(icon, out TMP_SpriteAsset value))
			{
				return value;
			}
			((Object)icon).name = name;
			TMP_SpriteAsset val = CreateAssetFor(icon, iconMetrics);
			Icons.Add(icon, val);
			return val;
		}

		private static TMP_SpriteAsset CreateAssetFor(Sprite sprite, GlyphMetrics iconMetrics)
		{
			//IL_0052: 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_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: 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_0076: 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_0089: Expected O, but got Unknown
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			Texture2D texture = sprite.texture;
			TMP_SpriteAsset val = ScriptableObject.CreateInstance<TMP_SpriteAsset>();
			val.version = "1.1.0";
			((Object)val).name = ((Object)sprite).name;
			((TMP_Asset)val).hashCode = TMP_TextUtilities.GetSimpleHashCode(((Object)val).name);
			val.spriteSheet = (Texture)(object)texture;
			val.spriteGlyphTable = new List<TMP_SpriteGlyph>();
			val.spriteCharacterTable = new List<TMP_SpriteCharacter>();
			TMP_SpriteGlyph val2 = new TMP_SpriteGlyph
			{
				index = 0u,
				metrics = iconMetrics,
				glyphRect = new GlyphRect(sprite.rect),
				scale = 1.25f,
				sprite = sprite
			};
			val.spriteGlyphTable.Add(val2);
			TMP_SpriteCharacter item = new TMP_SpriteCharacter(0u, val2)
			{
				name = ((Object)sprite).name,
				scale = 1.25f
			};
			val.spriteCharacterTable.Add(item);
			Material val3 = new Material(Shader.Find("TextMeshPro/Sprite"));
			val3.SetTexture(ShaderUtilities.ID_MainTex, val.spriteSheet);
			((TMP_Asset)val).material = val3;
			val.UpdateLookupTables();
			return val;
		}
	}
}
namespace COTL_API.Saves
{
	[Serializable]
	public class ObjectDictionary : Dictionary<string, object>
	{
		public ObjectDictionary()
		{
		}

		protected ObjectDictionary(SerializationInfo info, StreamingContext context)
			: base(info, context)
		{
		}

		public T? GetValue<T>(string key)
		{
			if (ContainsKey(key))
			{
				return (T)base[key];
			}
			return default(T);
		}

		public string? GetValueAsString(string key)
		{
			return GetValue<string>(key);
		}

		public int GetValueAsInt(string key)
		{
			long valueAsLong = GetValueAsLong(key);
			if (valueAsLong <= int.MaxValue)
			{
				if (valueAsLong < int.MinValue)
				{
					return int.MinValue;
				}
				return (int)valueAsLong;
			}
			return int.MaxValue;
		}

		public long GetValueAsLong(string key)
		{
			return GetValue<long>(key);
		}

		public float GetValueAsFloat(string key)
		{
			return Convert.ToSingle(GetValue<object>(key));
		}

		public bool GetValueAsBoolean(string key)
		{
			return GetValue<bool>(key);
		}

		public void SetValue<T>(string key, T? value)
		{
			if (value == null)
			{
				Remove(key);
			}
			else if (ContainsKey(key))
			{
				base[key] = value;
			}
			else
			{
				Add(key, value);
			}
		}
	}
	internal class ApiData
	{
		private readonly string[] _randomEasterEgg = new string[4] { "Rawr~", "Hewwo, twis pwoject was made bwy a fwwy, and I'm suwe you'ww wuv it!", "Another day another unstable API! Hello!", "Proud bug maker!" };

		public string OwO => _randomEasterEgg[Random.Range(0, _randomEasterEgg.Length)];

		public ObjectDictionary EnumData { get; set; } = new ObjectDictionary();

	}
	public class ApiSlotData
	{
		private readonly string[] _randomEasteregg = new string[4] { "Rawr~", "Hewwo, twis pwoject was made bwy a fwwy, and I'm suwe you'ww wuv it!", "Another day another unstable API! Hello!", "Proud bug maker!" };

		public string OwO => _randomEasteregg[Random.Range(0, _randomEasteregg.Length)];

		public Dictionary<int, CustomObjective> QuestData { get; set; } = new Dictionary<int, CustomObjective>();

	}
	public enum ModdedSaveLoadOrder
	{
		LOAD_AS_SOON_AS_POSSIBLE,
		LOAD_AFTER_SAVE_START
	}
	public abstract class BaseModdedSaveData
	{
		public abstract int SAVE_SLOT { get; protected set; }

		public abstract bool IsLoaded { get; protected set; }

		public abstract string GUID { get; protected set; }

		public abstract ModdedSaveLoadOrder LoadOrder { get; set; }

		public Action? OnSaveCompleted { get; set; }

		public Action<MMReadWriteError>? OnSaveError { get; set; }

		public Action? OnLoadComplete { get; set; }

		public Action<int>? OnSaveSlotDeleted { get; set; }

		public abstract void CreateDefault();

		public abstract void Save(bool encrypt = true, bool backup = true);

		public abstract void Load(int? saveSlot = null);

		public abstract bool SaveExist(int? saveSlot = null);

		public abstract void DeleteSaveSlot(int? saveSlot = null);

		public abstract void ResetSave(int? saveSlot = null, bool newGame = false);

		public abstract string MakeSaveSlot(int? slot = null);
	}
	public class ModdedSaveData<T> : BaseModdedSaveData where T : class, new()
	{
		private readonly COTLDataReadWriter<T> _dataReadWriter = new COTLDataReadWriter<T>();

		public override int SAVE_SLOT { get; protected set; } = 5;


		public override ModdedSaveLoadOrder LoadOrder { get; set; } = ModdedSaveLoadOrder.LOAD_AFTER_SAVE_START;


		public sealed override string GUID { get; protected set; }

		public override bool IsLoaded { get; protected set; }

		public T? Data { get; private set; }

		public ModdedSaveData(string guid)
		{
			GUID = guid;
			COTLDataReadWriter<T> dataReadWriter = _dataReadWriter;
			((MMDataReadWriterBase<T>)(object)dataReadWriter).OnReadCompleted = (Action<T>)Delegate.Combine(((MMDataReadWriterBase<T>)(object)dataReadWriter).OnReadCompleted, (Action<T>)delegate(T saveData)
			{
				Data = saveData;
				IsLoaded = true;
				base.OnLoadComplete?.Invoke();
			});
			COTLDataReadWriter<T> dataReadWriter2 = _dataReadWriter;
			((MMDataReadWriterBase<T>)(object)dataReadWriter2).OnCreateDefault = (Action)Delegate.Combine(((MMDataReadWriterBase<T>)(object)dataReadWriter2).OnCreateDefault, (Action)delegate
			{
				CreateDefault();
				base.OnLoadComplete?.Invoke();
				IsLoaded = true;
				base.OnSaveCompleted?.Invoke();
			});
			COTLDataReadWriter<T> dataReadWriter3 = _dataReadWriter;
			((MMDataReadWriterBase<T>)(object)dataReadWriter3).OnWriteCompleted = (Action)Delegate.Combine(((MMDataReadWriterBase<T>)(object)dataReadWriter3).OnWriteCompleted, (Action)delegate
			{
				base.OnSaveCompleted?.Invoke();
			});
			COTLDataReadWriter<T> dataReadWriter4 = _dataReadWriter;
			((MMDataReadWriterBase<T>)(object)dataReadWriter4).OnWriteError = (Action<MMReadWriteError>)Delegate.Combine(((MMDataReadWriterBase<T>)(object)dataReadWriter4).OnWriteError, (Action<MMReadWriteError>)delegate(MMReadWriteError error)
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				base.OnSaveError?.Invoke(error);
			});
		}

		public override void CreateDefault()
		{
			Data = new T();
		}

		public override void Save(bool encrypt = true, bool backup = true)
		{
			if ((LoadOrder == ModdedSaveLoadOrder.LOAD_AS_SOON_AS_POSSIBLE || (DataManager.Instance.AllowSaving && !CheatConsole.IN_DEMO)) && Data != null)
			{
				((MMDataReadWriterBase<T>)(object)_dataReadWriter).Write(Data, MakeSaveSlot((LoadOrder == ModdedSaveLoadOrder.LOAD_AS_SOON_AS_POSSIBLE) ? null : new int?(SAVE_SLOT)), encrypt, backup);
			}
		}

		public override void Load(int? saveSlot = null)
		{
			if (LoadOrder == ModdedSaveLoadOrder.LOAD_AS_SOON_AS_POSSIBLE || !CheatConsole.IN_DEMO)
			{
				if (saveSlot.HasValue)
				{
					SAVE_SLOT = saveSlot.Value;
				}
				((MMDataReadWriterBase<T>)(object)_dataReadWriter).Read(MakeSaveSlot((LoadOrder == ModdedSaveLoadOrder.LOAD_AS_SOON_AS_POSSIBLE) ? null : new int?(SAVE_SLOT)));
			}
		}

		public override bool SaveExist(int? saveSlot = null)
		{
			return ((MMDataReadWriterBase<T>)(object)_dataReadWriter).FileExists(MakeSaveSlot(saveSlot));
		}

		public override void DeleteSaveSlot(int? saveSlot = null)
		{
			((MMDataReadWriterBase<T>)(object)_dataReadWriter).Delete(MakeSaveSlot(saveSlot));
			if (saveSlot.HasValue)
			{
				base.OnSaveSlotDeleted?.Invoke(saveSlot.Value);
			}
		}

		public override void ResetSave(int? saveSlot = null, bool newGame = false)
		{
			if (saveSlot.HasValue)
			{
				SAVE_SLOT = saveSlot.Value;
			}
			CreateDefault();
			if (!newGame)
			{
				Save();
			}
			IsLoaded = true;
		}

		public override string MakeSaveSlot(int? slot = null)
		{
			if (!slot.HasValue)
			{
				return GUID + ".json";
			}
			return $"{GUID}_{slot}.json";
		}
	}
	[HarmonyPatch]
	public static class ModdedSaveManager
	{
		internal static readonly Dictionary<string, BaseModdedSaveData> ModdedSaveDataList = new Dictionary<string, BaseModdedSaveData>();

		public static void RegisterModdedSave(BaseModdedSaveData saveData)
		{
			ModdedSaveDataList.Add(saveData.GUID, saveData);
			if (saveData.LoadOrder == ModdedSaveLoadOrder.LOAD_AS_SOON_AS_POSSIBLE)
			{
				saveData.Load();
			}
		}

		[HarmonyPatch(typeof(SaveAndLoad), "Load")]
		[HarmonyPostfix]
		private static void SaveAndLoad_Load(int saveSlot)
		{
			foreach (BaseModdedSaveData item in ModdedSaveDataList.Values.Where((BaseModdedSaveData save) => save.LoadOrder != ModdedSaveLoadOrder.LOAD_AS_SOON_AS_POSSIBLE))
			{
				item.Load(saveSlot);
			}
		}

		[HarmonyPatch(typeof(SaveAndLoad), "Save")]
		[HarmonyPostfix]
		private static void SaveAndLoad_Save()
		{
			foreach (BaseModdedSaveData value in ModdedSaveDataList.Values)
			{
				value.Save();
			}
		}

		[HarmonyPatch(typeof(SaveAndLoad), "ResetSave")]
		[HarmonyPostfix]
		private static void SaveAndLoad_ResetSave(int saveSlot, bool newGame)
		{
			foreach (BaseModdedSaveData item in ModdedSaveDataList.Values.Where((BaseModdedSaveData save) => save.LoadOrder != ModdedSaveLoadOrder.LOAD_AS_SOON_AS_POSSIBLE))
			{
				item.ResetSave(saveSlot, newGame);
			}
		}

		[HarmonyPatch(typeof(SaveAndLoad), "DeleteSaveSlot")]
		[HarmonyPostfix]
		private static void SaveAndLoad_DeleteSaveSlot(int saveSlot)
		{
			foreach (BaseModdedSaveData item in ModdedSaveDataList.Values.Where((BaseModdedSaveData save) => save.LoadOrder != ModdedSaveLoadOrder.LOAD_AS_SOON_AS_POSSIBLE))
			{
				item.DeleteSaveSlot(saveSlot);
			}
		}
	}
}
namespace COTL_API.UI
{
	internal static class SettingsUtils
	{
		internal static GameObject? HeaderTemplate { get; set; }

		internal static GameObject? SliderTemplate { get; set; }

		internal static GameObject? DropdownTemplate { get; set; }

		internal static GameObject? HorizontalSelectorTemplate { get; set; }

		internal static GameObject? ToggleTemplate { get; set; }

		public static void AddHeader(Transform parent, string? text)
		{
			if ((Object)(object)HeaderTemplate == (Object)null)
			{
				LogHelper.LogError("Unable to find header template!");
				return;
			}
			GameObject obj = Object.Instantiate<GameObject>(HeaderTemplate, parent);
			((Object)obj).name = text;
			((TMP_Text)obj.GetComponentInChildren<TextMeshProUGUI>()).text = text;
		}

		public static void AddSlider(Transform parent, string text, float value, float minValue, float maxValue, int increment, ValueDisplayFormat format = 1, UnityAction<float>? onChange = null)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)SliderTemplate == (Object)null)
			{
				LogHelper.LogError("Unable to find slider template!");
				return;
			}
			GameObject obj = Object.Instantiate<GameObject>(SliderTemplate, parent);
			((Object)obj).name = text;
			((TMP_Text)obj.GetComponentInChildren<TextMeshProUGUI>()).text = text;
			MMSlider componentInChildren = obj.GetComponentInChildren<MMSlider>();
			((Slider)componentInChildren).minValue = minValue;
			((Slider)componentInChildren).maxValue = maxValue;
			componentInChildren._increment = increment;
			componentInChildren._valueDisplayFormat = format;
			if (onChange != null)
			{
				((UnityEvent<float>)(object)((Slider)componentInChildren).onValueChanged).AddListener(onChange);
			}
			((Slider)componentInChildren).value = value;
		}

		public static void AddDropdown(Transform parent, string text, string?[] options, int index = 0, Action<int>? onChange = null, string? indexStringOverride = null)
		{
			if ((Object)(object)DropdownTemplate == (Object)null)
			{
				LogHelper.LogError("Unable to find dropdown template!");
				return;
			}
			GameObject obj = Object.Instantiate<GameObject>(DropdownTemplate, parent);
			((Object)obj).name = text;
			((TMP_Text)obj.GetComponentInChildren<TextMeshProUGUI>()).text = text;
			MMDropdown componentInChildren = obj.GetComponentInChildren<MMDropdown>();
			componentInChildren._localizeContent = false;
			componentInChildren.UpdateContent(options);
			int num = Math.Max(0, ArrayExtensions.IndexOf<string>(options, indexStringOverride));
			componentInChildren.ContentIndex = ((indexStringOverride != null) ? num : index);
			if (onChange != null)
			{
				componentInChildren.OnValueChanged = (Action<int>)Delegate.Combine(componentInChildren.OnValueChanged, onChange);
			}
		}

		public static void AddKeyboardShortcutDropdown(Transform parent, string text, int index = 0, Action<KeyboardShortcut>? onChange = null, string? indexStringOverride = null)
		{
			Action<KeyboardShortcut> onChange2 = onChange;
			if ((Object)(object)DropdownTemplate == (Object)null)
			{
				LogHelper.LogError("Unable to find dropdown template!");
				return;
			}
			GameObject val = Object.Instantiate<GameObject>(DropdownTemplate, parent);
			((Object)val).name = text;
			((TMP_Text)val.GetComponentInChildren<TextMeshProUGUI>()).text = text;
			MMDropdown mmDropdown = val.GetComponentInChildren<MMDropdown>();
			mmDropdown._localizeContent = false;
			mmDropdown.UpdateContent(Enum.GetNames(typeof(KeyCode)));
			if (indexStringOverride != null)
			{
				index = Array.IndexOf<string>(mmDropdown.Content, indexStringOverride);
			}
			mmDropdown.ContentIndex = index;
			if (onChange2 != null)
			{
				MMDropdown obj = mmDropdown;
				obj.OnValueChanged = (Action<int>)Delegate.Combine(obj.OnValueChanged, (Action<int>)delegate(int selectedIndex)
				{
					//IL_001c: Unknown result type (might be due to invalid IL or missing references)
					//IL_0021: Unknown result type (might be due to invalid IL or missing references)
					//IL_0024: Unknown result type (might be due to invalid IL or missing references)
					//IL_0035: Unknown result type (might be due to invalid IL or missing references)
					KeyCode val2 = (KeyCode)Enum.Parse(typeof(KeyCode), mmDropdown.Content[selectedIndex]);
					KeyboardShortcut obj2 = default(KeyboardShortcut);
					((KeyboardShortcut)(ref obj2))..ctor(val2, Array.Empty<KeyCode>());
					onChange2(obj2);
				});
			}
		}

		public static void AddHorizontalSelector(Transform parent, string text, string?[] options, int index = 0, Action<int>? onChange = null, string? indexStringOverride = null)
		{
			if ((Object)(object)HorizontalSelectorTemplate == (Object)null)
			{
				LogHelper.LogError("Unable to find horizontal selector template!");
				return;
			}
			GameObject obj = Object.Instantiate<GameObject>(HorizontalSelectorTemplate, parent);
			((Object)obj).name = text;
			((TMP_Text)obj.GetComponentInChildren<TextMeshProUGUI>()).text = text;
			MMHorizontalSelector componentInChildren = obj.GetComponentInChildren<MMHorizontalSelector>();
			componentInChildren._localizeContent = false;
			componentInChildren.UpdateContent(options);
			int num = Math.Max(0, ArrayExtensions.IndexOf<string>(options, indexStringOverride));
			componentInChildren.ContentIndex = ((indexStringOverride != null) ? num : index);
			if (onChange != null)
			{
				componentInChildren.OnSelectionChanged = (Action<int>)Delegate.Combine(componentInChildren.OnSelectionChanged, onChange);
			}
		}

		public static void AddToggle(Transform parent, string text, bool value, Action<bool>? onChange = null)
		{
			if ((Object)(object)ToggleTemplate == (Object)null)
			{
				LogHelper.LogError("Unable to find toggle template!");
				return;
			}
			GameObject obj = Object.Instantiate<GameObject>(ToggleTemplate, parent);
			((Object)obj).name = text;
			((TMP_Text)obj.GetComponentInChildren<TextMeshProUGUI>()).text = text;
			MMToggle componentInChildren = obj.GetComponentInChildren<MMToggle>();
			componentInChildren.Value = value;
			componentInChildren.UpdateState(true);
			if (onChange != null)
			{
				componentInChildren.OnValueChanged = (Action<bool>)Delegate.Combine(componentInChildren.OnValueChanged, onChange);
			}
		}
	}
	[HarmonyPatch]
	public static class UIManager
	{
		public static Action OnSettingsLoaded { get; set; } = delegate
		{
		};


		[HarmonyPatch(typeof(UISettingsMenuController), "OnShowStarted")]
		[HarmonyPostfix]
		private static void UISettingsMenuController_OnShowStarted(UISettingsMenuController __instance)
		{
			//IL_02e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Expected O, but got Unknown
			if ((Object)(object)SettingsUtils.HeaderTemplate == (Object)null)
			{
				SettingsUtils.HeaderTemplate = ((Component)((Transform)((Component)__instance._graphicsSettings).GetComponentInChildren<ScrollRect>().content).GetChild(0)).gameObject;
			}
			if ((Object)(object)SettingsUtils.SliderTemplate == (Object)null)
			{
				SettingsUtils.SliderTemplate = ((Component)((Transform)((Component)__instance._gameSettings).GetComponentInChildren<ScrollRect>().content).GetChild(2)).gameObject;
			}
			if ((Object)(object)SettingsUtils.DropdownTemplate == (Object)null)
			{
				SettingsUtils.DropdownTemplate = ((Component)((Transform)((Component)__instance._graphicsSettings).GetComponentInChildren<ScrollRect>().content).GetChild(2)).gameObject;
			}
			if ((Object)(object)SettingsUtils.HorizontalSelectorTemplate == (Object)null)
			{
				SettingsUtils.HorizontalSelectorTemplate = ((Component)((Transform)((Component)__instance._graphicsSettings).GetComponentInChildren<ScrollRect>().content).GetChild(3)).gameObject;
			}
			if ((Object)(object)SettingsUtils.ToggleTemplate == (Object)null)
			{
				SettingsUtils.ToggleTemplate = ((Component)((Transform)((Component)__instance._graphicsSettings).GetComponentInChildren<ScrollRect>().content).GetChild(4)).gameObject;
			}
			GraphicsSettings graphicsSettings = __instance._graphicsSettings;
			SettingsTabNavigatorBase stnb = ((Component)((Component)__instance).transform).GetComponentInChildren<SettingsTabNavigatorBase>();
			HorizontalLayoutGroup componentInChildren = ((Component)stnb).GetComponentInChildren<HorizontalLayoutGroup>();
			Transform val = Object.Instantiate<Transform>(((Component)componentInChildren).transform.GetChild(2), ((Component)componentInChildren).transform);
			val.SetSiblingIndex(((Component)componentInChildren).transform.childCount - 2);
			((Object)val).name = "Mod Settings Button";
			TMP_Text componentInChildren2 = ((Component)val).GetComponentInChildren<TMP_Text>();
			Object.Destroy((Object)(object)((Component)val).GetComponentInChildren<Localize>());
			componentInChildren2.text = "Mods";
			GameObject gameObject = ((Component)((Component)((Component)__instance).GetComponentInChildren<GameSettings>()).transform.parent).gameObject;
			Transform obj = Object.Instantiate<Transform>(gameObject.transform.GetChild(1), gameObject.transform);
			((Object)obj).name = "Mod Settings Content";
			((Component)obj).gameObject.SetActive(true);
			GraphicsSettings componentInChildren3 = ((Component)obj).GetComponentInChildren<GraphicsSettings>();
			SettingsTab tab = ((Component)val).GetComponent<SettingsTab>();
			((MMTab)tab)._menu = (UISubmenuBase)(object)componentInChildren3;
			((UIMenuBase)componentInChildren3)._defaultSelectable = ((Component)((ScrollRect)componentInChildren3._scrollRect).content).GetComponentInChildren<Selectable>();
			((UIMenuBase)componentInChildren3)._defaultSelectableFallbacks = Array.Empty<Selectable>();
			Action onShow = ((UIMenuBase)graphicsSettings).OnShow;
			Action onHide = ((UIMenuBase)graphicsSettings).OnHide;
			Delegate[] invocationList = onShow.GetInvocationList();
			Delegate[] invocationList2 = onHide.GetInvocationList();
			Action action = (Action)invocationList[1];
			Action b = (Action)invocationList2[1];
			Action action2 = (Action)invocationList2[2];
			((UIMenuBase)componentInChildren3).OnShow = (Action)Delegate.Combine(((UIMenuBase)componentInChildren3).OnShow, action);
			((UIMenuBase)componentInChildren3).OnHide = (Action)Delegate.Combine(((UIMenuBase)componentInChildren3).OnHide, action2);
			((UIMenuBase)componentInChildren3).OnHide = (Action)Delegate.Combine(((UIMenuBase)componentInChildren3).OnHide, b);
			((UIMenuBase)graphicsSettings).OnShow = (Action)Delegate.Remove(((UIMenuBase)graphicsSettings).OnShow, action);
			((UIMenuBase)graphicsSettings).OnHide = (Action)Delegate.Remove(((UIMenuBase)graphicsSettings).OnHide, action2);
			((MMTabNavigatorBase<SettingsTab>)(object)((Component)((Component)__instance).transform).GetComponentInChildren<SettingsTabNavigatorBase>())._tabs = ((MMTabNavigatorBase<SettingsTab>)(object)((Component)((Component)__instance).transform).GetComponentInChildren<SettingsTabNavigatorBase>())._tabs.Append(tab).ToArray();
			MMButton componentInChildren4 = ((Component)val).GetComponentInChildren<MMButton>();
			((UnityEventBase)((Button)componentInChildren4).onClick).RemoveAllListeners();
			((UnityEvent)((Button)componentInChildren4).onClick).AddListener((UnityAction)delegate
			{
				((MMTabNavigatorBase<SettingsTab>)(object)stnb).TransitionTo(tab);
			});
		}

		[HarmonyPatch(typeof(GraphicsSettings), "OnShowStarted")]
		[HarmonyPrefix]
		private static void UISettingsMenuController_OnShowStarted(GraphicsSettings __instance)
		{
			if (!(((Object)__instance).name != "Mod Settings Content"))
			{
				__instance._targetFpsSelectable.HorizontalSelector._canvasGroup = ((UIMenuBase)__instance)._canvasGroup;
				((UIMenuBase)__instance)._defaultSelectable = ((Component)((ScrollRect)__instance._scrollRect).content).GetComponentInChildren<Selectable>();
				? val = MonoSingleton<UINavigatorNew>.Instance;
				Selectable defaultSelectable = ((UIMenuBase)__instance)._defaultSelectable;
				((UINavigatorNew)val).NavigateToNew((IMMSelectable)(object)((defaultSelectable is IMMSelectable) ? defaultSelectable : null));
			}
		}

		[HarmonyPatch(typeof(GraphicsSettings), "Start")]
		[HarmonyPrefix]
		private static bool GraphicsSettings_Start(GraphicsSettings __instance)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			if (((Object)__instance).name != "Mod Settings Content")
			{
				return true;
			}
			Transform content = (Transform)(object)((ScrollRect)__instance._scrollRect).content;
			foreach (Transform item in content)
			{
				Object.Destroy((Object)(object)((Component)item).gameObject);
			}
			OnSettingsLoaded();
			OnSettingsLoaded = delegate
			{
			};
			string text = null;
			foreach (ISettingsElement item2 in CustomSettingsManager.SettingsElements.OrderBy((ISettingsElement x) => x.Category))
			{
				if (item2.Category != text)
				{
					text = item2.Category;
					SettingsUtils.AddHeader(content, text);
				}
				Slider slider = item2 as Slider;
				Dropdown dropdown;
				KeyboardShortcutDropdown keyboardShortcutDropdown;
				HorizontalSelector horizontalSelector;
				Toggle toggle;
				if (slider == null)
				{
					dropdown = item2 as Dropdown;
					if (dropdown == null)
					{
						keyboardShortcutDropdown = item2 as KeyboardShortcutDropdown;
						if (keyboardShortcutDropdown == null)
						{
							horizontalSelector = item2 as HorizontalSelector;
							if (horizontalSelector == null)
							{
								toggle = item2 as Toggle;
								if (toggle != null)
								{
									SettingsUtils.AddToggle(content, toggle.Text, toggle.Value, OnValueChanged);
								}
							}
							else
							{
								SettingsUtils.AddHorizontalSelector(content, horizontalSelector.Text, horizontalSelector.Options, -1, OnValueChanged, horizontalSelector.Value);
							}
						}
						else
						{
							SettingsUtils.AddKeyboardShortcutDropdown(content, keyboardShortcutDropdown.Text, 0, OnValueChanged, keyboardShortcutDropdown.Value.ToString());
						}
					}
					else
					{
						SettingsUtils.AddDropdown(content, dropdown.Text, dropdown.Options, -1, OnValueChanged, dropdown.Value);
					}
				}
				else
				{
					SettingsUtils.AddSlider(content, slider.Text, slider.Value, slider.Min, slider.Max, slider.Increment, slider.DisplayFormat, OnValueChanged);
				}
				void OnValueChanged(bool i)
				{
					toggle.Value = i;
					toggle.OnValueChanged?.Invoke(i);
				}
				void OnValueChanged(int i)
				{
					horizontalSelector.Value = horizontalSelector.Options[i];
					horizontalSelector.OnValueChanged?.Invoke(i);
				}
				void OnValueChanged(KeyboardShortcut i)
				{
					//IL_0008: Unknown result type (might be due to invalid IL or missing references)
					//IL_0027: Unknown result type (might be due to invalid IL or missing references)
					keyboardShortcutDropdown.Value = ((KeyboardShortcut)(ref i)).MainKey;
					keyboardShortcutDropdown.OnValueChanged?.Invoke(i);
				}
				void OnValueChanged(int i)
				{
					dropdown.Value = dropdown.Options[i];
					dropdown.OnValueChanged?.Invoke(i);
				}
				void OnValueChanged(float i)
				{
					slider.Value = i;
					slider.OnValueChanged?.Invoke(i);
				}
			}
			if (!CustomSettingsManager.SettingsElements.Any())
			{
				SettingsUtils.AddHeader(content, "(No mods have settings)");
			}
			return false;
		}
	}
}
namespace COTL_API.UI.Helpers
{
	public static class GameHash
	{
		public static void LogGameInfo()
		{
			string gameAssemblyHash = GetGameAssemblyHash();
			LogHelper.LogInfo("Cult of the Lamb " + Application.version + " - SHA256 Hash: " + gameAssemblyHash);
		}

		private static string GetGameAssemblyHash()
		{
			byte[] buffer = File.ReadAllBytes(Assembly.GetAssembly(typeof(TwitchManager)).Location);
			byte[] array;
			using (SHA256 sHA = SHA256.Create())
			{
				array = sHA.ComputeHash(buffer);
			}
			return BitConverter.ToString(array).Replace("-", "");
		}

		private static bool VerifyAssemblyHash(string assemblyHash, string correctHash)
		{
			return assemblyHash.Equals(correctHash, StringComparison.OrdinalIgnoreCase);
		}
	}
	[HarmonyPatch]
	public static class ModdedStructuresPatches
	{
		private const string MiniMods = "InfernoDragon0.cotl.CotLChef";

		private static readonly string[] ModdedVanillaStructures = new string[2] { "Building Fishing Hut(Clone)", "Building Fishing Hut" };

		private static readonly string[] ModdedVanillaPrefabPaths = new string[1] { "Building Fishing Hut" };

		[HarmonyTranspiler]
		[HarmonyPatch(typeof(ControlUtilities), "GetCurrentInputType")]
		private static IEnumerable<CodeInstruction> ControlUtilities_GetCurrentInputType(IEnumerable<CodeInstruction> instructions, MethodBase originalMethod)
		{
			List<CodeInstruction> list = new List<CodeInstruction>(instructions);
			for (int i = 0; i < list.Count; i++)
			{
				if (list[i].opcode != OpCodes.Ldstr || !list[i].operand.ToString().Contains("Steam informs us the controller is a {0}"))
				{
					continue;
				}
				for (int j = i + 1; j < list.Count; j++)
				{
					if (!(list[j].opcode != OpCodes.Call) && list[j].operand is MethodInfo methodInfo && methodInfo.Name == "Log")
					{
						list.RemoveRange(i, j - i + 1);
						break;
					}
				}
				break;
			}
			return list.AsEnumerable();
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Debugger), "LogInvalidTween")]
		private static bool Debugger_LogInvalidTween()
		{
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Debug), "LogError", new Type[] { typeof(object) })]
		[HarmonyPatch(typeof(Debug), "LogError", new Type[]
		{
			typeof(object),
			typeof(Object)
		})]
		private static bool Debug_LogError(ref object message)
		{
			if (!(message is string text))
			{
				return true;
			}
			bool flag;
			switch (LocalizationManager.CurrentCulture.Name)
			{
			case "zh-CN":
			case "zh-TW":
			case "ja-JP":
			case "ko-KR":
				flag = true;
				break;
			default:
				flag = false;
				break;
			}
			if (!flag)
			{
				return !text.Contains("Font at path");
			}
			return true;
		}

		[HarmonyFinalizer]
		[HarmonyPatch(typeof(StructureBrain), "ApplyConfigToData")]
		[HarmonyPatch(typeof(LocationManager), "PlaceStructure")]
		private static Exception? Finalizer()
		{
			return null;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(GenerateRoom), "OnDisable")]
		private static void GenerateRoom_OnDisable(ref GenerateRoom __instance)
		{
			if (!ModdedVanillaStructureExists())
			{
				LogHelper.LogDebug("No modded vanilla structure mods found, checking for left over gameobjects.");
				RemoveModdedVanillaGameObjects();
			}
			LogHelper.LogDebug("Checking other custom structures and correcting DataManager (SaveData)");
			RemoveRogueCustomStructuresFromDataManager();
		}

		private static void RemoveModdedVanillaGameObjects()
		{
			List<GameObject> list = (from obj in Object.FindObjectsOfType<GameObject>()
				where ModdedVanillaStructures.Any(((Object)obj).name.Contains)
				select obj).ToList();
			if (!list.Any())
			{
				return;
			}
			foreach (GameObject item in list)
			{
				LogHelper.LogWarning("Destroyed " + ((Object)item).name);
				Object.DestroyImmediate((Object)(object)item);
			}
		}

		private static void RemoveRogueCustomStructuresFromDataManager()
		{
			Stopwatch stopwatch = new Stopwatch();
			stopwatch.Start();
			List<FieldInfo> list = (from a in AccessTools.GetDeclaredFields(typeof(DataManager))
				where a.FieldType == typeof(List<StructuresData>)
				select a).ToList();
			bool flag = false;
			foreach (FieldInfo field in list)
			{
				if (!(field.GetValue(DataManager.Instance) is List<StructuresData> list2))
				{
					continue;
				}
				List<StructuresData> itemsToRemove = new List<StructuresData>();
				list2.ForEach(delegate(StructuresData structure)
				{
					if (structure.PrefabPath != null && structure.PrefabPath.Contains("CustomBuildingPrefab"))
					{
						LogHelper.LogInfo("Found custom item in " + field.Name + ": " + structure.PrefabPath);
						if (!CustomStructureManager.CustomStructureExists(structure.PrefabPath))
						{
							LogHelper.LogWarning("Found custom item in " + field.Name + " from a mod no longer installed!: " + structure.PrefabPath);
							itemsToRemove.Add(structure);
						}
					}
				});
				int num = list2.RemoveAll((StructuresData a) => itemsToRemove.Contains(a));
				int num2 = 0;
				if (!ModdedVanillaStructureExists())
				{
					num2 = list2.RemoveAll((StructuresData a) => a == null || (a != null && a.PrefabPath != null && ModdedVanillaPrefabPaths.Any(a.PrefabPath.Contains)));
				}
				field.SetValue(DataManager.Instance, list2);
				if (num > 0 || num2 > 0)
				{
					flag = true;
					LogHelper.LogDebug($"Removed {num} orphaned structure(s) and {num2} orphaned modded vanilla structure(s) from {field.Name}.");
				}
			}
			stopwatch.Stop();
			if (flag)
			{
				LogHelper.LogDebug($"Finished correcting DataManager (SaveData) in {stopwatch.ElapsedMilliseconds}ms & {stopwatch.ElapsedTicks} ticks.");
				SaveAndLoad.Save();
			}
			else
			{
				LogHelper.LogDebug($"No orphaned structure(s), so no changes made to DataManager (SaveData) in {stopwatch.ElapsedMilliseconds}ms & {stopwatch.ElapsedTicks} ticks.");
			}
		}

		private static bool ModdedVanillaStructureExists()
		{
			return Chainloader.PluginInfos.FirstOrDefault((KeyValuePair<string, PluginInfo> a) => a.Value.Metadata.GUID.Contains("InfernoDragon0.cotl.CotLChef")).Value != null;
		}
	}
	public static class FontHelpers
	{
		internal static TMP_FontAsset? _startMenu { get; set; }

		internal static TMP_FontAsset? _pauseMenu { get; set; }

		public static TMP_FontAsset? PauseMenu => _pauseMenu;

		public static TMP_FontAsset? StartMenu => _startMenu;

		public static TMP_FontAsset? UIFont
		{
			get
			{
				if (!Object.op_Implicit((Object)(object)PauseMenu))
				{
					return StartMenu;
				}
				return PauseMenu;
			}
		}
	}
	public static class GameObjectExtensions
	{
		public static GameObject AttachToParent(this GameObject obj, Transform parent)
		{
			obj.transform.SetParent(parent);
			return obj;
		}

		public static GameObject ChangePosition(this GameObject obj, float? x = null, float? y = null, float? z = null)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			Quaternion localRotation = obj.transform.localRotation;
			float valueOrDefault = x.GetValueOrDefault();
			if (!x.HasValue)
			{
				valueOrDefault = localRotation.x;
				x = valueOrDefault;
			}
			valueOrDefault = y.GetValueOrDefault();
			if (!y.HasValue)
			{
				valueOrDefault = localRotation.y;
				y = valueOrDefault;
			}
			valueOrDefault = z.GetValueOrDefault();
			if (!z.HasValue)
			{
				valueOrDefault = localRotation.z;
				z = valueOrDefault;
			}
			obj.transform.localPosition = new Vector3(x.Value, y.Value, z.Value);
			return obj;
		}

		public static GameObject ChangeScale(this GameObject obj, float? x = null, float? y = null, float? z = null)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			Vector3 localScale = obj.transform.localScale;
			float valueOrDefault = x.GetValueOrDefault();
			if (!x.HasValue)
			{
				valueOrDefault = localScale.x;
				x = valueOrDefault;
			}
			valueOrDefault = y.GetValueOrDefault();
			if (!y.HasValue)
			{
				valueOrDefault = localScale.y;
				y = valueOrDefault;
			}
			valueOrDefault = z.GetValueOrDefault();
			if (!z.HasValue)
			{
				valueOrDefault = localScale.z;
				z = valueOrDefault;
			}
			((Vector3)(ref localScale))..ctor(x.Value, y.Value, z.Value);
			obj.transform.localScale = localScale;
			return obj;
		}

		public static GameObject ChangeRotation(this GameObject obj, float? x = null, float? y = null, float? z = null)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			Vector3 eulerAngles = obj.transform.eulerAngles;
			float valueOrDefault = x.GetValueOrDefault();
			if (!x.HasValue)
			{
				valueOrDefault = eulerAngles.x;
				x = valueOrDefault;
			}
			valueOrDefault = y.GetValueOrDefault();
			if (!y.HasValue)
			{
				valueOrDefault = eulerAngles.y;
				y = valueOrDefault;
			}
			valueOrDefault = z.GetValueOrDefault();
			if (!z.HasValue)
			{
				valueOrDefault = eulerAngles.z;
				z = valueOrDefault;
			}
			obj.transform.Rotate(new Vector3(x.Value, y.Value, z.Value));
			return obj;
		}

		public static GameObject CreateChild(this GameObject obj, string name)
		{
			Transform transform = obj.transform;
			return UIHelpers.CreateUIObject(name, transform);
		}

		public static GameObject MakeDraggable(this GameObject obj)
		{
			obj.AddComponent<UIBehaviourHelpers.DraggableUIObject>();
			return obj;
		}

		public static GameObject MakeDraggable(this GameObject obj, in RectTransform? dragRect)
		{
			obj.AddComponent<UIBehaviourHelpers.DraggableUIObject>().dragRectTransform = dragRect;
			return obj;
		}

		public static GameObject MakeDraggable(this GameObject obj, in GameObject dragObj)
		{
			UIBehaviourHelpers.DraggableUIObject draggableUIObject = obj.AddComponent<UIBehaviourHelpers.DraggableUIObject>();
			RectTransform component = dragObj.GetComponent<RectTransform>();
			draggableUIObject.dragRectTransform = component;
			return obj;
		}

		public static UIButton MakeButton(this GameObject obj)
		{
			return obj.AddComponent<UIButton>();
		}

		public static GameObject AddText(this GameObject obj, string message, float fontSize = 10f, TextAlignmentOptions alignment = 514)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			TextMeshProUGUI obj2 = obj.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj2).font = FontHelpers.UIFont;
			((TMP_Text)obj2).fontSize = fontSize;
			((TMP_Text)obj2).text = message;
			((TMP_Text)obj2).alignment = alignment;
			return obj;
		}

		public static GameObject EditText(this GameObject obj, string message)
		{
			TextMeshProUGUI component = obj.GetComponent<TextMeshProUGUI>();
			if ((Object)(object)component == (Object)null)
			{
				LogHelper.LogWarning("EditText: TextMeshProUGUI component not found.");
				return obj;
			}
			((TMP_Text)component).text = message;
			return obj;
		}

		private static string? GetPathToImage(string filename)
		{
			if (!Path.IsPathRooted(filename))
			{
				return Directory.GetFiles(Paths.PluginPath, filename, SearchOption.AllDirectories).FirstOrDefault();
			}
			return filename;
		}

		public static GameObject AttachImage(this GameObject obj, string imagePath, int opacity = 100)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			string pathToImage = GetPathToImage(imagePath);
			if (pathToImage == null)
			{
				LogHelper.LogError("File " + imagePath + " not found.");
				return obj;
			}
			Sprite sprite = TextureHelper.CreateSpriteFromPath(pathToImage);
			Image obj2 = obj.AddComponent<Image>();
			obj2.sprite = sprite;
			((Graphic)obj2).SetNativeSize();
			obj2.preserveAspect = true;
			opacity = Mathf.Clamp(opacity, 0, 100);
			Color color = ((Graphic)obj2).color;
			color.a = (float)opacity / 100f;
			((Graphic)obj2).color = color;
			return obj;
		}

		public static GameObject AttachImage(this GameObject obj, Sprite sprite, int opacity = 100)
		{
			//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_0046: Unknown result type (might be due to invalid IL or missing references)
			Image val = obj.AddComponent<Image>();
			val.sprite = sprite;
			((Graphic)val).SetNativeSize();
			val.preserveAspect = true;
			if ((opacity >= 100 || opacity < 0) ? true : false)
			{
				return obj;
			}
			Color color = ((Graphic)val).color;
			color.a = (float)opacity / 100f;
			((Graphic)val).color = color;
			return obj;
		}

		public static GameObject EditImage(this GameObject obj, Sprite sprite)
		{
			Image component = obj.GetComponent<Image>();
			if ((Object)(object)component == (Object)null)
			{
				LogHelper.LogError("EditImage: Image component not found.");
				return obj;
			}
			component.sprite = sprite;
			return obj;
		}

		public static GameObject EditImage(this GameObject obj, string imagePath)
		{
			string pathToImage = GetPathToImage(imagePath);
			if (pathToImage == null)
			{
				LogHelper.LogError("File " + imagePath + " not found.");
				return obj;
			}
			Sprite sprite = TextureHelper.CreateSpriteFromPath(pathToImage);
			Image component = obj.GetComponent<Image>();
			if ((Object)(object)component == (Object)null)
			{
				LogHelper.LogError("EditImage: Image component not found.");
				return obj;
			}
			component.sprite = sprite;
			return obj;
		}

		public static GameObject ChangeImageOpacity(this GameObject obj, int opacity = 100)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: 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)
			Image component = obj.GetComponent<Image>();
			if ((Object)(object)component == (Object)null)
			{
				LogHelper.LogError("ChangeOpacity: Image component not found.");
				return obj;
			}
			Color color = ((Graphic)component).color;
			opacity = Mathf.Clamp(opacity, 0, 100);
			color.a = (float)opacity / 100f;
			((Graphic)component).color = color;
			return obj;
		}
	}
	internal class UIBehaviourHelpers
	{
		public class DraggableUIObject : MonoBehaviour, IDragHandler, IEventSystemHandler
		{
			public RectTransform? dragRectTransform;

			public Canvas? canvas;

			public void Start()
			{
				if (dragRectTransform == null)
				{
					dragRectTransform = ((Component)this).GetComponent<RectTransform>();
				}
				if (canvas == null)
				{
					canvas = ((Component)this).GetComponentInParent<Canvas>();
				}
			}

			public void OnDrag(PointerEventData eventData)
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				//IL_0039: 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)
				if ((Object)(object)dragRectTransform != (Object)null && (Object)(object)canvas != (Object)null)
				{
					RectTransform? obj = dragRectTransform;
					obj.anchoredPosition += eventData.delta / canvas.scaleFactor;
				}
			}
		}
	}
	public class UIButton : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler, IPointerDownHandler
	{
		public delegate void ButtonAction();

		public event ButtonAction? OnClick;

		public event ButtonAction? OnCursorEnter;

		public event ButtonAction? OnCursorExit;

		public void OnPointerDown(PointerEventData eventData)
		{
			this.OnClick?.Invoke();
		}

		public void OnPointerEnter(PointerEventData eventData)
		{
			this.OnCursorEnter?.Invoke();
		}

		public void OnPointerExit(PointerEventData eventData)
		{
			this.OnCursorExit?.Invoke();
		}
	}
	public static class UIHelpers
	{
		public static LayerMask UILayer => LayerMask.op_Implicit(LayerMask.NameToLayer("UI"));

		public static void AddToPauseMenu<T>() where T : UIMenuBase
		{
			UIPatches.PauseMenuQueue.Add(typeof(T));
		}

		public static GameObject CreateUIObject(string name)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: 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_0037: Expected O, but got Unknown
			GameObject val = new GameObject(name)
			{
				layer = LayerMask.op_Implicit(UILayer)
			};
			val.transform.localPosition = Vector3.zero;
			val.transform.localScale = Vector3.one;
			return val;
		}

		public static GameObject CreateUIObject(string name, Transform parent)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Expected O, but got Unknown
			GameObject val = new GameObject(name)
			{
				layer = LayerMask.op_Implicit(UILayer)
			};
			val.transform.SetParent(parent);
			val.transform.localPosition = Vector3.zero;
			val.transform.localScale = Vector3.one;
			return val;
		}
	}
	public abstract class UIMenuBase : MonoBehaviour
	{
		public static Transform? Parent { get; set; }

		public void Start()
		{
			if ((Object)(object)Parent != (Object)null)
			{
				InitializeMenu(Parent);
			}
		}

		public abstract void InitializeMenu(Transform parent);
	}
	internal static class UIPatches
	{
		[HarmonyPatch]
		public static class PauseMenuPatch
		{
			[HarmonyPatch(typeof(UIPauseMenuController), "Start")]
			[HarmonyPostfix]
			public static void AddUIItems(UIPauseMenuController __instance)
			{
				//IL_0078: Unknown result type (might be due to invalid IL or missing references)
				//IL_0082: Expected O, but got Unknown
				//IL_0099: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b3: 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)
				Transform val = ((Component)__instance).gameObject.transform.Find("PauseMenuContainer");
				FontHelpers._pauseMenu = ((TMP_Text)((Component)((Component)((Component)((Component)((Component)val.Find("Left")).transform.Find("Transform")).transform.Find("MenuContainer")).transform.Find("Settings")).transform.Find("Text")).GetComponent<TextMeshProUGUI>()).font;
				GameObject container = new GameObject("COTL_API_MenuContainer");
				container.transform.SetParent(val);
				container.layer = LayerMask.op_Implicit(UIHelpers.UILayer);
				container.transform.position = Vector3.zero;
				container.transform.localScale = Vector3.one;
				UIMenuBase.Parent = container.transform;
				PauseMenuQueue.ForEach(delegate(Type x)
				{
					container.AddComponent(x);
				});
			}
		}

		[HarmonyPatch]
		public static class StartMenuPatch
		{
			[HarmonyPatch(typeof(MainMenuController), "Start")]
			[HarmonyPostfix]
			public static void AddUIItems(MainMenuController __instance)
			{
				FontHelpers._startMenu = ((TMP_Text)((Component)((Component)((Component)((Component)((Component)((Component)((Component)((Component)((Component)__instance).gameObject.transform.Find("Main Menu")).transform.Find("MainMenuContainer")).transform.Find("Left")).transform.Find("Transform")).transform.Find("MenusContainer")).transform.Find("MainMenu")).transform.Find("Settings")).transform.Find("Text (TMP)")).GetComponent<TextMeshProUGUI>()).font;
			}
		}

		public static readonly List<Type> PauseMenuQueue = new List<Type>();

		public static readonly List<Type> StartMenuQueue = new List<Type>();
	}
}
namespace COTL_API.Helpers
{
	public static class OnInteractHelper
	{
		[MethodImpl(MethodImplOptions.NoInlining)]
		[HarmonyPatch(typeof(Interaction), "OnInteract")]
		[HarmonyReversePatch(/*Could not decode attribute arguments.*/)]
		public static void Interaction_OnInteract(Interaction instance, StateMachine state)
		{
			if ((Object)(object)Plugin.Instance != (Object)null && Plugin.Instance.Debug)
			{
				LogHelper.LogWarning($"Interaction.OnInteract Test({instance}, {state})");
			}
		}
	}
	internal static class Debugging
	{
		public static void PrintStatistics(bool printNames = false)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<ITEM_TYPE, CustomInventoryItem> customItemList = CustomItemManager.CustomItemList;
			LogHelper.LogInfo($"Items: {customItemList.Count}");
			if (printNames)
			{
				foreach (KeyValuePair<ITEM_TYPE, CustomInventoryItem> item in customItemList)
				{
					LogHelper.LogInfo($"{item.Key}: {item.Value.InternalName}");
				}
			}
			Dictionary<TYPES, CustomStructure> customStructureList = CustomStructureManager.CustomStructureList;
			LogHelper.LogInfo($"Structures: {customStructureList.Count}");
			if (printNames)
			{
				foreach (KeyValuePair<TYPES, CustomStructure> item2 in customStructureList)
				{
					LogHelper.LogInfo($"{item2.Key}: {item2.Value.InternalName}");
				}
			}
			Dictionary<FollowerTaskType, CustomTask> customTaskList = CustomTaskManager.CustomTaskList;
			LogHelper.LogInfo($"Tasks: {customTaskList.Count}");
			if (printNames)
			{
				foreach (KeyValuePair<FollowerTaskType, CustomTask> item3 in customTaskList)
				{
					LogHelper.LogInfo($"{item3.Key}: {item3.Value.InternalName}");
				}
			}
			Dictionary<FollowerCommands, COTL_API.CustomFollowerCommand.CustomFollowerCommand> customFollowerCommandList = CustomFollowerCommandManager.CustomFollowerCommandList;
			LogHelper.LogInfo($"Commands: {customFollowerCommandList.Count}");
			if (printNames)
			{
				foreach (KeyValuePair<FollowerCommands, COTL_API.CustomFollowerCommand.CustomFollowerCommand> item4 in customFollowerCommandList)
				{
					LogHelper.LogInfo($"{item4.Key}: {item4.Value.InternalName}");
				}
			}
			Dictionary<ITEM_TYPE, COTL_API.CustomMission.CustomMission> customMissionList = CustomMissionManager.CustomMissionList;
			LogHelper.LogInfo($"Missions: {customMissionList.Count}");
			if (printNames)
			{
				foreach (KeyValuePair<ITEM_TYPE, COTL_API.CustomMission.CustomMission> item5 in customMissionList)
				{
					LogHelper.LogInfo($"{item5.Key}: {item5.Value.InternalName}");
				}
			}
			Dictionary<int, CustomObjective> customObjectiveList = CustomObjectiveManager.CustomObjectiveList;
			LogHelper.LogInfo($"Objectives: {customObjectiveList.Count}");
			if (printNames)
			{
				foreach (KeyValuePair<int, CustomObjective> item6 in customObjectiveList)
				{
					LogHelper.LogInfo($"{item6.Key}: {item6.Value.InitialQuestText}");
				}
			}
			Dictionary<RelicType, CustomRelicData> customRelicDataList = CustomRelicManager.CustomRelicDataList;
			LogHelper.LogInfo($"Relics: {customRelicDataList.Count}");
			if (printNames)
			{
				foreach (KeyValuePair<RelicType, CustomRelicData> item7 in customRelicDataList)
				{
					LogHelper.LogInfo($"{item7.Key}: {item7.Value.InternalName}");
				}
			}
			Dictionary<string, CustomStructure> prefabStrings = CustomPrefabManager.PrefabStrings;
			LogHelper.LogInfo($"Prefabs: {prefabStrings.Count}");
			if (!printNames)
			{
				return;
			}
			foreach (KeyValuePair<string, CustomStructure> item8 in prefabStrings)
			{
				LogHelper.LogInfo(item8.Key + ": " + item8.Value.InternalName);
			}
		}
	}
	public static class Extensions
	{
		public static bool TryAdd<TKey, TValue>(this IDictionary<TKey, TValue> dictionary, TKey key, TValue value)
		{
			if (dictionary.ContainsKey(key))
			{
				return false;
			}
			dictionary.Add(key, value);
			return true;
		}
	}
	public static class HashCode
	{
		public static int GetNameHashCode(string str)
		{
			return str.Aggregate(0, (int current, char c) => (current << 3) - current + c);
		}

		public static int GetValueHashCode(string str)
		{
			return str.Aggregate(0, (int current, char c) => ((current << 5) + current) ^ c);
		}
	}
	public static class ItemPickUp
	{
		public static GameObject? GetItemPickUpObject(ITEM_TYPE type)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Expected I4, but got Unknown
			LogHelper.LogWarning($"ImitatePickUpObject: {type}");
			string text = "";
			switch ((int)type)
			{
			case 1:
				text = "Log";
				break;
			case 2:
				text = "Rock1";
				break;
			case 3:
				text = "Rock2";
				break;
			case 4:
				text = "Rock3";
				break;
			case 5:
				text = "Seed - Sword";
				break;
			case 6:
				text = "Meat";
				break;
			case 7:
				text = "Wheat";
				break;
			case 8:
				text = "Seed";
				break;
			case 9:
				text = "VileBones";
				break;
			case 10:
				text = "Soul";
				break;
			case 11:
				text = "GildedVine";
				break;
			case 12:
				text = "Red Heart";
				break;
			case 13:
				text = "Half Heart";
				break;
			case 14:
				text = "Blue Heart";
				break;
			case 15:
				text = "Half Blue Heart";
				break;
			case 16:
				text = "Time Token";
				break;
			case 17:
				text = "Generic Pick Up";
				break;
			case 18:
				text = "StainedGlass";
				break;
			case 19:
				text = "SacredFlower";
				break;
			case 20:
				text = "Bla