Decompiled source of SenpaisChest v2.2.4

SenpaisChest.dll

Decompiled 16 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using PSS;
using SenpaisChest.ChestLabels;
using SenpaisChest.ChestLabels.Extensions;
using SenpaisChest.Config;
using SenpaisChest.Data;
using SenpaisChest.Integration;
using SenpaisChest.UI;
using SunHavenMuseumUtilityTracker;
using SunHavenMuseumUtilityTracker.Data;
using SunhavenMods.Shared;
using SunhavenTodo;
using SunhavenTodo.Data;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
using UnityEngine.UI;
using Wish;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("SenpaisChest")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+215d19542340737939c33a78dbefe54932fcbb1c")]
[assembly: AssemblyProduct("SenpaisChest")]
[assembly: AssemblyTitle("SenpaisChest")]
[assembly: InternalsVisibleTo("HavenDevTools")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SunhavenMods.Shared
{
	public static class VersionChecker
	{
		public class VersionCheckResult
		{
			public bool Success { get; set; }

			public bool UpdateAvailable { get; set; }

			public string CurrentVersion { get; set; }

			public string LatestVersion { get; set; }

			public string ModName { get; set; }

			public string NexusUrl { get; set; }

			public string Changelog { get; set; }

			public string ErrorMessage { get; set; }
		}

		private class VersionCheckRunner : MonoBehaviour
		{
			public void StartCheck(string pluginGuid, string currentVersion, Action<VersionCheckResult> onComplete)
			{
				((MonoBehaviour)this).StartCoroutine(CheckVersionCoroutine(pluginGuid, currentVersion, onComplete));
			}

			private IEnumerator CheckVersionCoroutine(string pluginGuid, string currentVersion, Action<VersionCheckResult> onComplete)
			{
				VersionCheckResult result = new VersionCheckResult
				{
					CurrentVersion = currentVersion
				};
				UnityWebRequest www = UnityWebRequest.Get("https://azraelgodking.github.io/SunhavenMod/versions.json");
				try
				{
					www.timeout = 10;
					yield return www.SendWebRequest();
					if ((int)www.result == 2 || (int)www.result == 3)
					{
						result.Success = false;
						result.ErrorMessage = "Network error: " + www.error;
						LogWarning(result.ErrorMessage);
						onComplete?.Invoke(result);
						Object.Destroy((Object)(object)((Component)this).gameObject);
						yield break;
					}
					try
					{
						string json = www.downloadHandler.text;
						string modPattern = "\"" + Regex.Escape(pluginGuid) + "\"\\s*:\\s*\\{([^}]+)\\}";
						Match modMatch = Regex.Match(json, modPattern, RegexOptions.Singleline);
						if (!modMatch.Success)
						{
							result.Success = false;
							result.ErrorMessage = "Mod '" + pluginGuid + "' not found in versions.json";
							LogWarning(result.ErrorMessage);
							onComplete?.Invoke(result);
							Object.Destroy((Object)(object)((Component)this).gameObject);
							yield break;
						}
						string modJson = modMatch.Groups[1].Value;
						result.LatestVersion = ExtractJsonString(modJson, "version");
						result.ModName = ExtractJsonString(modJson, "name");
						result.NexusUrl = ExtractJsonString(modJson, "nexus");
						result.Changelog = ExtractJsonString(modJson, "changelog");
						if (string.IsNullOrEmpty(result.LatestVersion))
						{
							result.Success = false;
							result.ErrorMessage = "Could not parse version from response";
							LogWarning(result.ErrorMessage);
							onComplete?.Invoke(result);
							Object.Destroy((Object)(object)((Component)this).gameObject);
							yield break;
						}
						result.Success = true;
						result.UpdateAvailable = CompareVersions(currentVersion, result.LatestVersion) < 0;
						if (result.UpdateAvailable)
						{
							Log("Update available for " + result.ModName + ": " + currentVersion + " -> " + result.LatestVersion);
						}
						else
						{
							Log(result.ModName + " is up to date (v" + currentVersion + ")");
						}
					}
					catch (Exception ex)
					{
						result.Success = false;
						result.ErrorMessage = "Parse error: " + ex.Message;
						LogError(result.ErrorMessage);
					}
				}
				finally
				{
					((IDisposable)www)?.Dispose();
				}
				onComplete?.Invoke(result);
				Object.Destroy((Object)(object)((Component)this).gameObject);
			}

			private string ExtractJsonString(string json, string key)
			{
				string pattern = "\"" + key + "\"\\s*:\\s*(?:\"([^\"]*)\"|null)";
				Match match = Regex.Match(json, pattern);
				return match.Success ? match.Groups[1].Value : null;
			}
		}

		private const string VersionsUrl = "https://azraelgodking.github.io/SunhavenMod/versions.json";

		private static ManualLogSource _logger;

		public static void CheckForUpdate(string pluginGuid, string currentVersion, ManualLogSource logger = null, Action<VersionCheckResult> onComplete = null)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			_logger = logger;
			VersionCheckRunner versionCheckRunner = new GameObject("VersionChecker").AddComponent<VersionCheckRunner>();
			Object.DontDestroyOnLoad((Object)(object)((Component)versionCheckRunner).gameObject);
			SceneRootSurvivor.TryRegisterPersistentRunnerGameObject(((Component)versionCheckRunner).gameObject);
			versionCheckRunner.StartCheck(pluginGuid, currentVersion, onComplete);
		}

		public static int CompareVersions(string v1, string v2)
		{
			if (string.IsNullOrEmpty(v1) || string.IsNullOrEmpty(v2))
			{
				return 0;
			}
			v1 = v1.TrimStart('v', 'V');
			v2 = v2.TrimStart('v', 'V');
			string[] array = v1.Split(new char[1] { '.' });
			string[] array2 = v2.Split(new char[1] { '.' });
			int num = Math.Max(array.Length, array2.Length);
			for (int i = 0; i < num; i++)
			{
				int result;
				int num2 = ((i < array.Length && int.TryParse(array[i], out result)) ? result : 0);
				int result2;
				int num3 = ((i < array2.Length && int.TryParse(array2[i], out result2)) ? result2 : 0);
				if (num2 < num3)
				{
					return -1;
				}
				if (num2 > num3)
				{
					return 1;
				}
			}
			return 0;
		}

		internal static void Log(string message)
		{
			ManualLogSource logger = _logger;
			if (logger != null)
			{
				logger.LogInfo((object)("[VersionChecker] " + message));
			}
		}

		internal static void LogWarning(string message)
		{
			ManualLogSource logger = _logger;
			if (logger != null)
			{
				logger.LogWarning((object)("[VersionChecker] " + message));
			}
		}

		internal static void LogError(string message)
		{
			ManualLogSource logger = _logger;
			if (logger != null)
			{
				logger.LogError((object)("[VersionChecker] " + message));
			}
		}
	}
	public static class VersionCheckerExtensions
	{
		public static void NotifyUpdateAvailable(this VersionChecker.VersionCheckResult result, ManualLogSource logger = null)
		{
			if (!result.UpdateAvailable)
			{
				return;
			}
			string text = result.ModName + " update available: v" + result.LatestVersion;
			try
			{
				Type type = ReflectionHelper.FindWishType("NotificationStack");
				if (type != null)
				{
					Type type2 = ReflectionHelper.FindType("SingletonBehaviour`1", "Wish");
					if (type2 != null)
					{
						Type type3 = type2.MakeGenericType(type);
						object obj = type3.GetProperty("Instance")?.GetValue(null);
						if (obj != null)
						{
							MethodInfo method = type.GetMethod("SendNotification", new Type[5]
							{
								typeof(string),
								typeof(int),
								typeof(int),
								typeof(bool),
								typeof(bool)
							});
							if (method != null)
							{
								method.Invoke(obj, new object[5] { text, 0, 1, false, true });
								return;
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				if (logger != null)
				{
					logger.LogWarning((object)("Failed to send native notification: " + ex.Message));
				}
			}
			if (logger != null)
			{
				logger.LogWarning((object)("[UPDATE AVAILABLE] " + text));
			}
			if (!string.IsNullOrEmpty(result.NexusUrl) && logger != null)
			{
				logger.LogWarning((object)("Download at: " + result.NexusUrl));
			}
		}
	}
	public static class SceneRootSurvivor
	{
		private static readonly object Lock = new object();

		private static readonly List<string> NoKillSubstrings = new List<string>();

		private static Harmony _harmony;

		public static void TryRegisterPersistentRunnerGameObject(GameObject go)
		{
			if (!((Object)(object)go == (Object)null))
			{
				TryAddNoKillListSubstring(((Object)go).name);
			}
		}

		public static void TryAddNoKillListSubstring(string nameSubstring)
		{
			if (string.IsNullOrEmpty(nameSubstring))
			{
				return;
			}
			lock (Lock)
			{
				bool flag = false;
				for (int i = 0; i < NoKillSubstrings.Count; i++)
				{
					if (string.Equals(NoKillSubstrings[i], nameSubstring, StringComparison.OrdinalIgnoreCase))
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					NoKillSubstrings.Add(nameSubstring);
				}
			}
			EnsurePatched();
		}

		private static void EnsurePatched()
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Expected O, but got Unknown
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Expected O, but got Unknown
			if (_harmony != null)
			{
				return;
			}
			lock (Lock)
			{
				if (_harmony == null)
				{
					MethodInfo methodInfo = AccessTools.Method(typeof(Scene), "GetRootGameObjects", Type.EmptyTypes, (Type[])null);
					if (!(methodInfo == null))
					{
						string text = typeof(SceneRootSurvivor).Assembly.GetName().Name ?? "Unknown";
						Harmony val = new Harmony("SunhavenMods.SceneRootSurvivor." + text);
						val.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(SceneRootSurvivor), "OnGetRootGameObjectsPostfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						_harmony = val;
					}
				}
			}
		}

		private static void OnGetRootGameObjectsPostfix(ref GameObject[] __result)
		{
			if (__result == null || __result.Length == 0)
			{
				return;
			}
			List<string> list;
			lock (Lock)
			{
				if (NoKillSubstrings.Count == 0)
				{
					return;
				}
				list = new List<string>(NoKillSubstrings);
			}
			List<GameObject> list2 = new List<GameObject>(__result);
			for (int i = 0; i < list.Count; i++)
			{
				string noKill = list[i];
				list2.RemoveAll((GameObject a) => (Object)(object)a != (Object)null && ((Object)a).name.IndexOf(noKill, StringComparison.OrdinalIgnoreCase) >= 0);
			}
			__result = list2.ToArray();
		}
	}
	public static class ReflectionHelper
	{
		public static readonly BindingFlags AllBindingFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;

		public static Type FindType(string typeName, params string[] namespaces)
		{
			Type type = AccessTools.TypeByName(typeName);
			if (type != null)
			{
				return type;
			}
			foreach (string text in namespaces)
			{
				type = AccessTools.TypeByName(text + "." + typeName);
				if (type != null)
				{
					return type;
				}
			}
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				try
				{
					type = assembly.GetTypes().FirstOrDefault((Type t) => t.Name == typeName || t.FullName == typeName);
					if (type != null)
					{
						return type;
					}
				}
				catch (ReflectionTypeLoadException)
				{
				}
			}
			return null;
		}

		public static Type FindWishType(string typeName)
		{
			return FindType(typeName, "Wish");
		}

		public static object GetStaticValue(Type type, string memberName)
		{
			if (type == null)
			{
				return null;
			}
			PropertyInfo property = type.GetProperty(memberName, AllBindingFlags);
			if (property != null && property.GetMethod != null)
			{
				return property.GetValue(null);
			}
			FieldInfo field = type.GetField(memberName, AllBindingFlags);
			if (field != null)
			{
				return field.GetValue(null);
			}
			return null;
		}

		public static object GetSingletonInstance(Type type)
		{
			if (type == null)
			{
				return null;
			}
			string[] array = new string[5] { "Instance", "instance", "_instance", "Singleton", "singleton" };
			string[] array2 = array;
			foreach (string memberName in array2)
			{
				object staticValue = GetStaticValue(type, memberName);
				if (staticValue != null)
				{
					return staticValue;
				}
			}
			return null;
		}

		public static object GetInstanceValue(object instance, string memberName)
		{
			if (instance == null)
			{
				return null;
			}
			Type type = instance.GetType();
			while (type != null)
			{
				PropertyInfo property = type.GetProperty(memberName, AllBindingFlags);
				if (property != null && property.GetMethod != null)
				{
					return property.GetValue(instance);
				}
				FieldInfo field = type.GetField(memberName, AllBindingFlags);
				if (field != null)
				{
					return field.GetValue(instance);
				}
				type = type.BaseType;
			}
			return null;
		}

		public static bool SetInstanceValue(object instance, string memberName, object value)
		{
			if (instance == null)
			{
				return false;
			}
			Type type = instance.GetType();
			while (type != null)
			{
				PropertyInfo property = type.GetProperty(memberName, AllBindingFlags);
				if (property != null && property.SetMethod != null)
				{
					property.SetValue(instance, value);
					return true;
				}
				FieldInfo field = type.GetField(memberName, AllBindingFlags);
				if (field != null)
				{
					field.SetValue(instance, value);
					return true;
				}
				type = type.BaseType;
			}
			return false;
		}

		public static object InvokeMethod(object instance, string methodName, params object[] args)
		{
			if (instance == null)
			{
				return null;
			}
			Type type = instance.GetType();
			Type[] array = args?.Select((object a) => a?.GetType() ?? typeof(object)).ToArray() ?? Type.EmptyTypes;
			MethodInfo methodInfo = AccessTools.Method(type, methodName, array, (Type[])null);
			if (methodInfo == null)
			{
				methodInfo = type.GetMethod(methodName, AllBindingFlags);
			}
			if (methodInfo == null)
			{
				return null;
			}
			return methodInfo.Invoke(instance, args);
		}

		public static object InvokeStaticMethod(Type type, string methodName, params object[] args)
		{
			if (type == null)
			{
				return null;
			}
			Type[] array = args?.Select((object a) => a?.GetType() ?? typeof(object)).ToArray() ?? Type.EmptyTypes;
			MethodInfo methodInfo = AccessTools.Method(type, methodName, array, (Type[])null);
			if (methodInfo == null)
			{
				methodInfo = type.GetMethod(methodName, AllBindingFlags);
			}
			if (methodInfo == null)
			{
				return null;
			}
			return methodInfo.Invoke(null, args);
		}

		public static FieldInfo[] GetAllFields(Type type)
		{
			if (type == null)
			{
				return Array.Empty<FieldInfo>();
			}
			FieldInfo[] fields = type.GetFields(AllBindingFlags);
			IEnumerable<FieldInfo> second;
			if (!(type.BaseType != null) || !(type.BaseType != typeof(object)))
			{
				second = Enumerable.Empty<FieldInfo>();
			}
			else
			{
				IEnumerable<FieldInfo> allFields = GetAllFields(type.BaseType);
				second = allFields;
			}
			return fields.Concat(second).Distinct().ToArray();
		}

		public static PropertyInfo[] GetAllProperties(Type type)
		{
			if (type == null)
			{
				return Array.Empty<PropertyInfo>();
			}
			PropertyInfo[] properties = type.GetProperties(AllBindingFlags);
			IEnumerable<PropertyInfo> second;
			if (!(type.BaseType != null) || !(type.BaseType != typeof(object)))
			{
				second = Enumerable.Empty<PropertyInfo>();
			}
			else
			{
				IEnumerable<PropertyInfo> allProperties = GetAllProperties(type.BaseType);
				second = allProperties;
			}
			return (from p in properties.Concat(second)
				group p by p.Name into g
				select g.First()).ToArray();
		}

		public static T TryGetValue<T>(object instance, string memberName, T defaultValue = default(T))
		{
			try
			{
				object instanceValue = GetInstanceValue(instance, memberName);
				if (instanceValue is T result)
				{
					return result;
				}
				if (instanceValue != null && typeof(T).IsAssignableFrom(instanceValue.GetType()))
				{
					return (T)instanceValue;
				}
				return defaultValue;
			}
			catch
			{
				return defaultValue;
			}
		}
	}
	public static class ItemSearch
	{
		private static readonly ManualLogSource _log = Logger.CreateLogSource("ItemSearch");

		private static object _dbInstance;

		private static FieldInfo _dictField;

		private static readonly List<KeyValuePair<int, string>> _bufferExact = new List<KeyValuePair<int, string>>();

		private static readonly List<KeyValuePair<int, string>> _bufferStartsWith = new List<KeyValuePair<int, string>>();

		private static readonly List<KeyValuePair<int, string>> _bufferContains = new List<KeyValuePair<int, string>>();

		public static string FormatDisplay(string name, int itemId)
		{
			if (string.IsNullOrEmpty(name))
			{
				return $"#{itemId}";
			}
			return $"{name} (#{itemId})";
		}

		public static List<KeyValuePair<int, string>> SearchItems(string query, int maxResults = 50)
		{
			List<KeyValuePair<int, string>> list = new List<KeyValuePair<int, string>>();
			if (string.IsNullOrEmpty(query) || query.Trim().Length < 2)
			{
				return list;
			}
			try
			{
				Dictionary<int, ItemSellInfo> itemDictionary = GetItemDictionary();
				if (itemDictionary == null)
				{
					return list;
				}
				string text = query.Trim().ToLowerInvariant();
				int result;
				bool flag = int.TryParse(query.Trim(), out result);
				_bufferExact.Clear();
				_bufferStartsWith.Clear();
				_bufferContains.Clear();
				foreach (KeyValuePair<int, ItemSellInfo> item2 in itemDictionary)
				{
					int key = item2.Key;
					string text2 = item2.Value?.name;
					if (!string.IsNullOrEmpty(text2))
					{
						KeyValuePair<int, string> item = new KeyValuePair<int, string>(key, text2);
						string text3 = text2.ToLowerInvariant();
						if (flag && key == result)
						{
							_bufferExact.Add(item);
						}
						else if (text3 == text)
						{
							_bufferExact.Add(item);
						}
						else if (text3.StartsWith(text))
						{
							_bufferStartsWith.Add(item);
						}
						else if (text3.Contains(text))
						{
							_bufferContains.Add(item);
						}
						else if (flag && key.ToString().Contains(query.Trim()))
						{
							_bufferContains.Add(item);
						}
					}
				}
				_bufferStartsWith.Sort((KeyValuePair<int, string> a, KeyValuePair<int, string> b) => string.Compare(a.Value, b.Value, StringComparison.OrdinalIgnoreCase));
				_bufferContains.Sort((KeyValuePair<int, string> a, KeyValuePair<int, string> b) => string.Compare(a.Value, b.Value, StringComparison.OrdinalIgnoreCase));
				list.AddRange(_bufferExact);
				list.AddRange(_bufferStartsWith);
				list.AddRange(_bufferContains);
				if (list.Count > maxResults)
				{
					list.RemoveRange(maxResults, list.Count - maxResults);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogDebug((object)("[ItemSearch] SearchItems error: " + ex.Message));
				}
			}
			return list;
		}

		public static string GetItemName(int itemId)
		{
			try
			{
				Dictionary<int, ItemSellInfo> itemDictionary = GetItemDictionary();
				if (itemDictionary == null || !itemDictionary.ContainsKey(itemId))
				{
					return null;
				}
				return itemDictionary[itemId]?.name;
			}
			catch (Exception ex)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogDebug((object)$"[ItemSearch] GetItemName({itemId}): {ex.Message}");
				}
				return null;
			}
		}

		public static ItemSellInfo GetItemSellInfo(int itemId)
		{
			try
			{
				Dictionary<int, ItemSellInfo> itemDictionary = GetItemDictionary();
				if (itemDictionary != null && itemDictionary.TryGetValue(itemId, out var value))
				{
					return value;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogDebug((object)$"[ItemSearch] GetItemSellInfo({itemId}): {ex.Message}");
				}
			}
			return null;
		}

		private static Dictionary<int, ItemSellInfo> GetItemDictionary()
		{
			try
			{
				if (_dbInstance != null)
				{
					object dbInstance = _dbInstance;
					Object val = (Object)((dbInstance is Object) ? dbInstance : null);
					if (val == null || !(val == (Object)null))
					{
						goto IL_006e;
					}
				}
				_dbInstance = null;
				_dictField = null;
				_dbInstance = GetSingletonInstance("Wish.ItemInfoDatabase");
				if (_dbInstance != null)
				{
					_dictField = _dbInstance.GetType().GetField("allItemSellInfos", BindingFlags.Instance | BindingFlags.Public);
				}
				goto IL_006e;
				IL_006e:
				if (_dbInstance == null || _dictField == null)
				{
					return null;
				}
				return _dictField.GetValue(_dbInstance) as Dictionary<int, ItemSellInfo>;
			}
			catch (Exception ex)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogDebug((object)("[ItemSearch] GetItemDictionary: " + ex.Message));
				}
				return null;
			}
		}

		private static object GetSingletonInstance(string typeName)
		{
			try
			{
				Type type = AccessTools.TypeByName("Wish.SingletonBehaviour`1");
				if (type == null)
				{
					return null;
				}
				Type type2 = AccessTools.TypeByName(typeName);
				if (type2 == null)
				{
					return null;
				}
				Type type3 = type.MakeGenericType(type2);
				return type3.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public | BindingFlags.FlattenHierarchy)?.GetValue(null);
			}
			catch (Exception ex)
			{
				ManualLogSource log = _log;
				if (log != null)
				{
					log.LogDebug((object)("[ItemSearch] GetSingletonInstance(" + typeName + "): " + ex.Message));
				}
				return null;
			}
		}
	}
	public static class TextInputFocusGuard
	{
		private const float DefaultPollIntervalSeconds = 0.25f;

		private static float _nextPollTime = -1f;

		private static bool _cachedDefer;

		private static bool _tmpTypeLookupDone;

		private static Type _tmpInputFieldType;

		private static bool _qcLookupDone;

		private static Type _qcType;

		private static PropertyInfo _qcInstanceProp;

		private static PropertyInfo _qcIsActiveProp;

		private static FieldInfo _qcIsActiveField;

		public static bool ShouldDeferModHotkeys(ManualLogSource debugLog = null, float pollIntervalSeconds = 0.25f)
		{
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (realtimeSinceStartup < _nextPollTime)
			{
				return _cachedDefer;
			}
			_nextPollTime = realtimeSinceStartup + Mathf.Max(0.05f, pollIntervalSeconds);
			bool flag = false;
			try
			{
				if (GUIUtility.keyboardControl != 0)
				{
					flag = true;
				}
				if (!flag)
				{
					EventSystem current = EventSystem.current;
					GameObject val = ((current != null) ? current.currentSelectedGameObject : null);
					if ((Object)(object)val != (Object)null)
					{
						if ((Object)(object)val.GetComponent<InputField>() != (Object)null)
						{
							flag = true;
						}
						else if (TryGetTmpInputField(val))
						{
							flag = true;
						}
					}
				}
				if (!flag && IsQuantumConsoleActive())
				{
					flag = true;
				}
			}
			catch (Exception ex)
			{
				if (debugLog != null)
				{
					debugLog.LogDebug((object)("[TextInputFocusGuard] " + ex.Message));
				}
			}
			_cachedDefer = flag;
			return flag;
		}

		private static bool TryGetTmpInputField(GameObject go)
		{
			if (!_tmpTypeLookupDone)
			{
				_tmpTypeLookupDone = true;
				_tmpInputFieldType = AccessTools.TypeByName("TMPro.TMP_InputField");
			}
			if (_tmpInputFieldType == null)
			{
				return false;
			}
			return (Object)(object)go.GetComponent(_tmpInputFieldType) != (Object)null;
		}

		private static bool IsQuantumConsoleActive()
		{
			try
			{
				if (!_qcLookupDone)
				{
					_qcLookupDone = true;
					_qcType = AccessTools.TypeByName("QFSW.QC.QuantumConsole");
					if (_qcType != null)
					{
						_qcInstanceProp = AccessTools.Property(_qcType, "Instance");
						_qcIsActiveProp = AccessTools.Property(_qcType, "IsActive");
						_qcIsActiveField = AccessTools.Field(_qcType, "isActive") ?? AccessTools.Field(_qcType, "_isActive");
					}
				}
				if (_qcType == null)
				{
					return false;
				}
				object obj = _qcInstanceProp?.GetValue(null);
				if (obj == null)
				{
					return false;
				}
				if (_qcIsActiveProp != null && _qcIsActiveProp.PropertyType == typeof(bool))
				{
					return (bool)_qcIsActiveProp.GetValue(obj);
				}
				if (_qcIsActiveField != null && _qcIsActiveField.FieldType == typeof(bool))
				{
					return (bool)_qcIsActiveField.GetValue(obj);
				}
			}
			catch
			{
			}
			return false;
		}
	}
}
namespace SenpaisChest
{
	[BepInPlugin("com.azraelgodking.senpaischest", "Senpai's Chest", "2.2.4")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private static SmartChestManager _staticManager;

		private static SmartChestSaveSystem _staticSaveSystem;

		private static SmartChestUI _staticUI;

		private static SmartChestConfig _staticConfig;

		private static MuseumTodoIntegration _museumTodoIntegration;

		internal static Chest CurrentInteractingChest;

		private static string _gameplaySessionCharacter;

		private static bool _applicationQuitting;

		private static readonly Dictionary<int, float> _sceneDiscardSuppressByHandle = new Dictionary<int, float>();

		private const float SceneDiscardSuppressSeconds = 20f;

		private Harmony _harmony;

		private SmartChestManager _manager;

		private SmartChestSaveSystem _saveSystem;

		private SmartChestUI _ui;

		private SmartChestConfig _config;

		private static GameObject _persistentRunner;

		private static SmartChestPersistentRunner _updateRunner;

		private bool _wasInMenuScene = true;

		private static GameObject _pendingChestPanel;

		private static Chest _pendingChest;

		private static int _pendingChestButtonFrames;

		private const string SenpaisChestConfigPanelName = "SenpaisChest_ConfigPanel";

		public static Plugin Instance { get; private set; }

		public static ManualLogSource Log { get; private set; }

		public static ConfigFile ConfigFile { get; private set; }

		private void Awake()
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Expected O, but got Unknown
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Expected O, but got Unknown
			//IL_01f1: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ConfigFile = CreateNamedConfig();
			Log.LogInfo((object)"Loading Senpai's Chest v2.2.4");
			CreatePersistentRunner();
			try
			{
				_config = new SmartChestConfig();
				_config.Initialize(ConfigFile);
				_staticConfig = _config;
				_config.UIScale.SettingChanged += delegate
				{
					float scale = Mathf.Clamp(_config.UIScale.Value, 0.5f, 2.5f);
					_staticUI?.SetScale(scale);
				};
				_manager = new SmartChestManager();
				_saveSystem = new SmartChestSaveSystem(_manager);
				_staticManager = _manager;
				_staticSaveSystem = _saveSystem;
				GameObject val = new GameObject("SenpaisChest_UI");
				Object.DontDestroyOnLoad((Object)(object)val);
				_ui = val.AddComponent<SmartChestUI>();
				_ui.Initialize(_manager);
				_ui.SetScale(Mathf.Clamp(_config.UIScale.Value, 0.5f, 2.5f));
				_staticUI = _ui;
				_harmony = new Harmony("com.azraelgodking.senpaischest");
				ApplyPatches();
				InitializeIntegrations();
				SceneManager.sceneLoaded += OnSceneLoaded;
				SceneManager.activeSceneChanged += OnActiveSceneChanged;
				if (_config.CheckForUpdates.Value)
				{
					VersionChecker.CheckForUpdate("com.azraelgodking.senpaischest", "2.2.4", Log, delegate(VersionChecker.VersionCheckResult result)
					{
						result.NotifyUpdateAvailable(Log);
					});
				}
				Log.LogInfo((object)"Senpai's Chest loaded successfully!");
				Log.LogInfo((object)string.Format("Press {0}{1} to configure a chest while interacting with it", _config.RequireCtrlModifier.Value ? "Ctrl+" : "", _config.ToggleKey.Value));
				if (_config.EnableChestLabels.Value)
				{
					Log.LogInfo((object)"Chest Labels enabled - labels shown above Chest and BankChest (not Hoppers/Animal Feeders)");
				}
			}
			catch (Exception arg)
			{
				Log.LogError((object)string.Format("Failed to load {0}: {1}", "Senpai's Chest", arg));
			}
		}

		private void CreatePersistentRunner()
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Expected O, but got Unknown
			if ((Object)(object)_persistentRunner != (Object)null)
			{
				Log.LogInfo((object)"PersistentRunner already exists");
				return;
			}
			_persistentRunner = new GameObject("SenpaisChest_PersistentRunner");
			Object.DontDestroyOnLoad((Object)(object)_persistentRunner);
			((Object)_persistentRunner).hideFlags = (HideFlags)61;
			SceneRootSurvivor.TryRegisterPersistentRunnerGameObject(_persistentRunner);
			_updateRunner = _persistentRunner.AddComponent<SmartChestPersistentRunner>();
			Log.LogInfo((object)"Created hidden PersistentRunner");
		}

		private static ConfigFile CreateNamedConfig()
		{
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Expected O, but got Unknown
			string text = Path.Combine(Paths.ConfigPath, "SenpaisChest.cfg");
			string text2 = Path.Combine(Paths.ConfigPath, "com.azraelgodking.senpaischest.cfg");
			try
			{
				if (!File.Exists(text) && File.Exists(text2))
				{
					File.Copy(text2, text);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("[Config] Migration to SenpaisChest.cfg failed: " + ex.Message));
				}
			}
			return new ConfigFile(text, true);
		}

		public static void EnsureUIComponentsExist()
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Expected O, but got Unknown
			try
			{
				if ((Object)(object)_persistentRunner == (Object)null || (Object)(object)_updateRunner == (Object)null)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogInfo((object)"[EnsureUI] Recreating PersistentRunner...");
					}
					_persistentRunner = new GameObject("SenpaisChest_PersistentRunner");
					Object.DontDestroyOnLoad((Object)(object)_persistentRunner);
					((Object)_persistentRunner).hideFlags = (HideFlags)61;
					SceneRootSurvivor.TryRegisterPersistentRunnerGameObject(_persistentRunner);
					_updateRunner = _persistentRunner.AddComponent<SmartChestPersistentRunner>();
				}
				if ((Object)(object)_staticUI == (Object)null)
				{
					ManualLogSource log2 = Log;
					if (log2 != null)
					{
						log2.LogInfo((object)"[EnsureUI] Recreating SmartChestUI...");
					}
					GameObject val = new GameObject("SenpaisChest_UI");
					Object.DontDestroyOnLoad((Object)(object)val);
					_staticUI = val.AddComponent<SmartChestUI>();
					_staticUI.Initialize(_staticManager);
					_staticUI.SetScale(Mathf.Clamp(_staticConfig.UIScale.Value, 0.5f, 2.5f));
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log3 = Log;
				if (log3 != null)
				{
					log3.LogError((object)("[EnsureUI] Error recreating UI: " + ex.Message));
				}
			}
		}

		private void InitializeIntegrations()
		{
			try
			{
				Dictionary<string, PluginInfo> pluginInfos = Chainloader.PluginInfos;
				bool flag = pluginInfos.ContainsKey("com.azraelgodking.sunhavenmuseumutilitytracker");
				bool flag2 = pluginInfos.ContainsKey("com.azraelgodking.sunhaventodo");
				if (flag && flag2)
				{
					_museumTodoIntegration = new MuseumTodoIntegration();
					return;
				}
				if (!flag)
				{
					Log.LogInfo((object)"[Integrations] S.M.U.T. not found");
				}
				if (!flag2)
				{
					Log.LogInfo((object)"[Integrations] SunhavenTodo not found");
				}
				Log.LogInfo((object)"[Integrations] Museum todo integration disabled (requires both S.M.U.T. and Todo)");
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("[Integrations] Error initializing: " + ex.Message));
			}
		}

		private void ApplyPatches()
		{
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Expected O, but got Unknown
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Expected O, but got Unknown
			//IL_0239: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Expected O, but got Unknown
			//IL_02b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_02be: Expected O, but got Unknown
			//IL_0327: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Expected O, but got Unknown
			//IL_03b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c2: Expected O, but got Unknown
			//IL_0443: Unknown result type (might be due to invalid IL or missing references)
			//IL_0450: Expected O, but got Unknown
			try
			{
				PatchMethod(typeof(Player), "InitializeAsOwner", typeof(Plugin), "OnPlayerInitialized");
				PatchMethod(typeof(Chest), "Interact", typeof(Plugin), "OnChestInteract", new Type[1] { typeof(int) });
				MethodInfo methodInfo = AccessTools.Method(typeof(Chest), "EndInteract", new Type[1] { typeof(int) }, (Type[])null);
				if (methodInfo != null)
				{
					HarmonyMethod val = new HarmonyMethod(AccessTools.Method(typeof(Plugin), "OnChestEndInteract_Prefix", (Type[])null, (Type[])null));
					_harmony.Patch((MethodBase)methodInfo, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)"Patched Chest.EndInteract (prefix)");
				}
				else
				{
					Log.LogWarning((object)"Could not find method Chest.EndInteract");
				}
				Type type = AccessTools.TypeByName("Wish.UIHandler");
				Type type2 = AccessTools.TypeByName("Wish.IExternalUIHandler");
				if (type != null && type2 != null)
				{
					MethodInfo methodInfo2 = AccessTools.Method(type, "OpenUI", new Type[5]
					{
						typeof(GameObject),
						typeof(Transform),
						typeof(bool),
						typeof(bool),
						type2
					}, (Type[])null);
					if (methodInfo2 != null)
					{
						HarmonyMethod val2 = new HarmonyMethod(AccessTools.Method(typeof(Plugin), "OnUIHandlerOpenUI_Postfix", (Type[])null, (Type[])null));
						_harmony.Patch((MethodBase)methodInfo2, (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Log.LogInfo((object)"Patched UIHandler.OpenUI (postfix)");
					}
					else
					{
						Log.LogWarning((object)"Could not find method UIHandler.OpenUI");
					}
				}
				else
				{
					Log.LogWarning((object)"Could not find Wish.UIHandler or Wish.IExternalUIHandler for chest button integration");
				}
				MethodInfo methodInfo3 = AccessTools.Method(typeof(Input), "GetKeyDown", new Type[1] { typeof(KeyCode) }, (Type[])null);
				if (methodInfo3 != null)
				{
					_harmony.Patch((MethodBase)methodInfo3, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "OnInputGetKeyDown_Prefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)"Patched Input.GetKeyDown (prefix)");
				}
				MethodInfo methodInfo4 = AccessTools.Method(typeof(Input), "GetKey", new Type[1] { typeof(KeyCode) }, (Type[])null);
				if (methodInfo4 != null)
				{
					_harmony.Patch((MethodBase)methodInfo4, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "OnInputGetKey_Prefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)"Patched Input.GetKey (prefix)");
				}
				MethodInfo methodInfo5 = AccessTools.Method(typeof(Input), "GetButtonDown", new Type[1] { typeof(string) }, (Type[])null);
				if (methodInfo5 != null)
				{
					_harmony.Patch((MethodBase)methodInfo5, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "OnInputGetButtonDown_Prefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)"Patched Input.GetButtonDown (prefix)");
				}
				Type type3 = AccessTools.TypeByName("Wish.PlayerInput");
				if (type3 != null)
				{
					MethodInfo methodInfo6 = AccessTools.Method(type3, "GetButtonDown", new Type[1] { typeof(string) }, (Type[])null);
					if (methodInfo6 != null)
					{
						_harmony.Patch((MethodBase)methodInfo6, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "OnPlayerInputGetButtonDown_Prefix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						Log.LogInfo((object)"Patched PlayerInput.GetButtonDown(string) (prefix)");
					}
					else
					{
						Log.LogWarning((object)"Could not find method PlayerInput.GetButtonDown(string)");
					}
				}
				else
				{
					Log.LogWarning((object)"Could not find Wish.PlayerInput type for UICancel blocking");
				}
				MethodInfo methodInfo7 = AccessTools.Method(typeof(Chest), "OnDisable", (Type[])null, (Type[])null);
				if (methodInfo7 != null)
				{
					_harmony.Patch((MethodBase)methodInfo7, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(Plugin), "OnChestOnDisable_Postfix", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)"Patched Chest.OnDisable (cleanup when chest removed from world)");
				}
				ApplyChestLabelPatches();
				Log.LogInfo((object)"Harmony patches applied successfully");
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Failed to apply patches: {arg}");
			}
		}

		private void ApplyChestLabelPatches()
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Expected O, but got Unknown
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected O, but got Unknown
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Expected O, but got Unknown
			Type typeFromHandle = typeof(ChestLabelPatch);
			MethodInfo methodInfo = AccessTools.Method(typeFromHandle, "SetMeta_Postfix", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeFromHandle, "OnEnable_Postfix", (Type[])null, (Type[])null);
			MethodInfo methodInfo3 = AccessTools.Method(typeFromHandle, "InteractionPoint_Postfix", (Type[])null, (Type[])null);
			string[] array = new string[3] { "SetMeta", "ReceiveNewMeta", "SaveMeta" };
			foreach (string text in array)
			{
				MethodInfo methodInfo4 = AccessTools.Method(typeof(Chest), text, (Type[])null, (Type[])null);
				if (methodInfo4 != null)
				{
					_harmony.Patch((MethodBase)methodInfo4, (HarmonyMethod)null, new HarmonyMethod(methodInfo), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)("Patched Chest." + text + " (labels)"));
				}
			}
			MethodInfo methodInfo5 = AccessTools.Method(typeof(Chest), "OnEnable", (Type[])null, (Type[])null);
			if (methodInfo5 != null)
			{
				_harmony.Patch((MethodBase)methodInfo5, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Log.LogInfo((object)"Patched Chest.OnEnable (labels)");
			}
			MethodInfo methodInfo6 = AccessTools.Method(typeof(Chest), "get_InteractionPoint", (Type[])null, (Type[])null);
			if (methodInfo6 != null)
			{
				_harmony.Patch((MethodBase)methodInfo6, (HarmonyMethod)null, new HarmonyMethod(methodInfo3), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Log.LogInfo((object)"Patched Chest.get_InteractionPoint (labels)");
			}
		}

		private void PatchMethod(Type targetType, string methodName, Type patchType, string patchMethodName, Type[] parameters = null)
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			MethodInfo methodInfo = ((parameters != null) ? AccessTools.Method(targetType, methodName, parameters, (Type[])null) : AccessTools.Method(targetType, methodName, (Type[])null, (Type[])null));
			if (methodInfo == null)
			{
				Log.LogWarning((object)("Could not find method " + targetType.Name + "." + methodName));
				return;
			}
			MethodInfo methodInfo2 = AccessTools.Method(patchType, patchMethodName, (Type[])null, (Type[])null);
			_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			Log.LogInfo((object)("Patched " + targetType.Name + "." + methodName));
		}

		private static void OnPlayerInitialized(Player __instance)
		{
			try
			{
				if ((Object)(object)__instance != (Object)(object)Player.Instance)
				{
					return;
				}
				EnsureUIComponentsExist();
				string text = null;
				CharacterData currentCharacter = GameSave.CurrentCharacter;
				if (currentCharacter != null)
				{
					text = currentCharacter.characterName;
				}
				if (string.IsNullOrEmpty(text))
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogWarning((object)"Player initialized but no character name found");
					}
					return;
				}
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogInfo((object)("Player initialized: " + text));
				}
				_staticManager?.SetCharacterName(text);
				_museumTodoIntegration?.Reset();
				SmartChestSaveData data = _staticSaveSystem?.Load(text);
				_staticManager?.LoadData(data);
				_gameplaySessionCharacter = text;
			}
			catch (Exception arg)
			{
				ManualLogSource log3 = Log;
				if (log3 != null)
				{
					log3.LogError((object)$"Error in OnPlayerInitialized: {arg}");
				}
			}
		}

		private static void OnChestInteract(Chest __instance, int interactType)
		{
			if (interactType != 0)
			{
				return;
			}
			CurrentInteractingChest = __instance;
			try
			{
				Type type = ((object)__instance).GetType();
				FieldInfo field = type.GetField("ui", BindingFlags.Instance | BindingFlags.NonPublic);
				if (!(field != null))
				{
					return;
				}
				object? value = field.GetValue(__instance);
				GameObject val = (GameObject)((value is GameObject) ? value : null);
				if (val != null && (Object)(object)val != (Object)null)
				{
					_pendingChestPanel = val;
					_pendingChest = __instance;
					_pendingChestButtonFrames = 3;
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogInfo((object)$"[SenpaisChest] Scheduled embedded panel from Chest.Interact (will add in 3 frames) - UI active: {val.activeInHierarchy}");
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogDebug((object)("[SenpaisChest] Could not schedule chest button: " + ex.Message));
				}
			}
		}

		private static void OnChestOnDisable_Postfix(Chest __instance)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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)
			try
			{
				if (_applicationQuitting || !Application.isPlaying || (Object)(object)__instance == (Object)null)
				{
					return;
				}
				GameObject gameObject = ((Component)__instance).gameObject;
				if ((Object)(object)gameObject == (Object)null)
				{
					return;
				}
				Scene scene = gameObject.scene;
				if (!((Scene)(ref scene)).IsValid())
				{
					return;
				}
				if (IsDiscardedSceneSuppressed(scene))
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogDebug((object)("[SenpaisChest] OnDisable: skip rule removal (scene '" + ((Scene)(ref scene)).name + "' discarded)"));
					}
					return;
				}
				string chestId = SmartChestManager.GetChestId(__instance);
				if (!string.IsNullOrEmpty(chestId) && _staticManager != null && _staticManager.RemoveSmartChest(chestId))
				{
					ManualLogSource log2 = Log;
					if (log2 != null)
					{
						log2.LogInfo((object)("[SenpaisChest] Removed smart chest rules (chest left world): " + chestId));
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log3 = Log;
				if (log3 != null)
				{
					log3.LogError((object)("[SenpaisChest] OnChestOnDisable_Postfix: " + ex.Message));
				}
			}
		}

		private static bool OnInputGetKeyDown_Prefix(KeyCode key, ref bool __result)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			if ((int)key != 8)
			{
				return true;
			}
			if (!SmartChestConfig.StaticBlockInputWhenTyping)
			{
				return true;
			}
			if (!SmartChestUI.ShouldBlockGameInput(_staticUI))
			{
				return true;
			}
			__result = false;
			return false;
		}

		private static bool OnInputGetKey_Prefix(KeyCode key, ref bool __result)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			if ((int)key != 8)
			{
				return true;
			}
			if (!SmartChestConfig.StaticBlockInputWhenTyping)
			{
				return true;
			}
			if (!SmartChestUI.ShouldBlockGameInput(_staticUI))
			{
				return true;
			}
			__result = false;
			return false;
		}

		private static bool OnInputGetButtonDown_Prefix(string buttonName, ref bool __result)
		{
			if (string.IsNullOrEmpty(buttonName))
			{
				return true;
			}
			if (!buttonName.Equals("Cancel", StringComparison.OrdinalIgnoreCase))
			{
				return true;
			}
			if (!SmartChestConfig.StaticBlockInputWhenTyping)
			{
				return true;
			}
			if (!SmartChestUI.ShouldBlockGameInput(_staticUI))
			{
				return true;
			}
			__result = false;
			return false;
		}

		private static bool OnPlayerInputGetButtonDown_Prefix(string button, ref bool __result)
		{
			if (!SmartChestConfig.StaticBlockInputWhenTyping)
			{
				return true;
			}
			if (!SmartChestUI.ShouldBlockGameInput(_staticUI))
			{
				return true;
			}
			if (button == "UICancel" || button == "Close")
			{
				__result = false;
				return false;
			}
			return true;
		}

		private static bool OnChestEndInteract_Prefix(Chest __instance, int interactType)
		{
			if ((Object)(object)CurrentInteractingChest == (Object)(object)__instance && (Object)(object)_staticUI != (Object)null && _staticUI.IsVisible && !_staticUI.IsEmbedded)
			{
				return false;
			}
			if ((Object)(object)CurrentInteractingChest == (Object)(object)__instance)
			{
				CurrentInteractingChest = null;
				_staticUI?.Hide();
			}
			return true;
		}

		private static void OnUIHandlerOpenUI_Postfix(object __instance, GameObject ui, Transform parent, bool playAudio, bool animate, object externalUIHandler)
		{
			if ((Object)(object)ui == (Object)null || externalUIHandler == null)
			{
				return;
			}
			Chest val = (Chest)((externalUIHandler is Chest) ? externalUIHandler : null);
			if (val == null)
			{
				return;
			}
			try
			{
				_pendingChestPanel = ui;
				_pendingChest = val;
				_pendingChestButtonFrames = 3;
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)$"[SenpaisChest] Scheduled embedded panel (will add in 3 frames) - UI active: {ui.activeInHierarchy}");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[SenpaisChest] Failed to schedule embedded panel: " + ex.Message));
				}
			}
		}

		internal static void ProcessPendingChestButton()
		{
			//IL_0174: Unknown result type (might be due to invalid IL or missing references)
			if (_pendingChestButtonFrames <= 0 || (Object)(object)_pendingChestPanel == (Object)null || (Object)(object)_pendingChest == (Object)null)
			{
				return;
			}
			_pendingChestButtonFrames--;
			if (_pendingChestButtonFrames != 0)
			{
				return;
			}
			GameObject pendingChestPanel = _pendingChestPanel;
			Chest pendingChest = _pendingChest;
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)$"[SenpaisChest] Processing pending panel: panel={(Object)(object)pendingChestPanel != (Object)null}, active={((pendingChestPanel != null) ? new bool?(pendingChestPanel.activeInHierarchy) : null)}, chest={(Object)(object)pendingChest != (Object)null}");
			}
			if ((Object)(object)pendingChestPanel == (Object)null || !pendingChestPanel.activeInHierarchy)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogInfo((object)$"[SenpaisChest] Skip add panel: panel null or inactive (panel={(Object)(object)pendingChestPanel != (Object)null}, active={((pendingChestPanel != null) ? new bool?(pendingChestPanel.activeInHierarchy) : null)})");
				}
				_pendingChestPanel = null;
				_pendingChest = null;
				return;
			}
			Canvas componentInParent = pendingChestPanel.GetComponentInParent<Canvas>();
			ManualLogSource log3 = Log;
			if (log3 != null)
			{
				log3.LogInfo((object)$"[SenpaisChest] Chest UI state - Canvas: {(Object)(object)componentInParent != (Object)null}, Canvas active: {((componentInParent != null) ? new bool?(((Component)componentInParent).gameObject.activeInHierarchy) : null)}, RenderMode: {((componentInParent != null) ? new RenderMode?(componentInParent.renderMode) : null)}");
			}
			try
			{
				AddSenpaisChestNotePanel(pendingChestPanel, pendingChest);
			}
			catch (Exception ex)
			{
				ManualLogSource log4 = Log;
				if (log4 != null)
				{
					log4.LogWarning((object)("[SenpaisChest] Failed to add embedded panel: " + ex.Message + "\n" + ex.StackTrace));
				}
			}
			finally
			{
				_pendingChestPanel = null;
				_pendingChest = null;
			}
		}

		private static void AddSenpaisChestNotePanel(GameObject chestUiRoot, Chest chest)
		{
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Expected O, but got Unknown
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Unknown result type (might be due to invalid IL or missing references)
			//IL_025c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0261: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0295: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)chestUiRoot == (Object)null || !chestUiRoot.activeInHierarchy)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogDebug((object)$"[SenpaisChest] Cannot add panel: chestUiRoot is null or inactive (null={(Object)(object)chestUiRoot == (Object)null}, active={((chestUiRoot != null) ? new bool?(chestUiRoot.activeInHierarchy) : null)})");
				}
				return;
			}
			Transform val = chestUiRoot.transform.Find("SenpaisChest_ConfigPanel");
			if ((Object)(object)val != (Object)null)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogInfo((object)$"[SenpaisChest] Panel already exists, reusing - active: {((Component)val).gameObject.activeInHierarchy}");
				}
				SmartChestUI uI = GetUI();
				if ((Object)(object)uI != (Object)null)
				{
					uI.ShowNoteForChest(chest, ((Component)val).gameObject);
				}
				return;
			}
			Canvas componentInParent = chestUiRoot.GetComponentInParent<Canvas>();
			if ((Object)(object)componentInParent == (Object)null)
			{
				ManualLogSource log3 = Log;
				if (log3 != null)
				{
					log3.LogWarning((object)"[SenpaisChest] Chest UI root is not under a Canvas, cannot create embedded panel");
				}
				return;
			}
			Transform transform = chestUiRoot.transform;
			try
			{
				GameObject val2 = new GameObject("SenpaisChest_ConfigPanel");
				val2.transform.SetParent(transform, false);
				val2.transform.SetAsLastSibling();
				val2.SetActive(true);
				RectTransform val3 = val2.AddComponent<RectTransform>();
				val3.anchorMin = new Vector2(0.5f, 0f);
				val3.anchorMax = new Vector2(0.5f, 0f);
				val3.pivot = new Vector2(0.5f, 0f);
				val3.anchoredPosition = Vector2.zero;
				val3.sizeDelta = new Vector2(340f, 34f);
				ManualLogSource log4 = Log;
				if (log4 != null)
				{
					log4.LogInfo((object)$"[SenpaisChest] Panel RectTransform - anchorMin={val3.anchorMin}, anchorMax={val3.anchorMax}, sizeDelta={val3.sizeDelta}, rect={val3.rect}");
				}
				CanvasGroup val4 = val2.AddComponent<CanvasGroup>();
				val4.blocksRaycasts = false;
				val4.interactable = false;
				val4.alpha = 1f;
				LayoutRebuilder.ForceRebuildLayoutImmediate(val3);
				Rect rect = val3.rect;
				if (!(((Rect)(ref rect)).width <= 0f))
				{
					rect = val3.rect;
					if (!(((Rect)(ref rect)).height <= 0f))
					{
						SmartChestUI uI2 = GetUI();
						if ((Object)(object)uI2 != (Object)null)
						{
							uI2.ShowNoteForChest(chest, val2);
							ManualLogSource log5 = Log;
							if (log5 != null)
							{
								log5.LogInfo((object)$"[SenpaisChest] Added note panel (Press F9 to configure) - chestUiRoot active: {chestUiRoot.activeInHierarchy}, panel active: {val2.activeInHierarchy}, rect: {val3.rect}");
							}
						}
						else
						{
							ManualLogSource log6 = Log;
							if (log6 != null)
							{
								log6.LogWarning((object)"[SenpaisChest] UI component is null, cannot show embedded panel");
							}
						}
						return;
					}
				}
				ManualLogSource log7 = Log;
				if (log7 != null)
				{
					rect = val3.rect;
					object arg = ((Rect)(ref rect)).width;
					rect = val3.rect;
					log7.LogWarning((object)$"[SenpaisChest] Panel rect is invalid (width={arg}, height={((Rect)(ref rect)).height}), waiting one more frame");
				}
				_pendingChestPanel = chestUiRoot;
				_pendingChest = chest;
				_pendingChestButtonFrames = 1;
			}
			catch (Exception arg2)
			{
				ManualLogSource log8 = Log;
				if (log8 != null)
				{
					log8.LogError((object)$"[SenpaisChest] Exception creating embedded panel: {arg2}");
				}
			}
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			bool flag = ((Scene)(ref scene)).name == "MainMenu" || ((Scene)(ref scene)).name == "Menu";
			if (flag && !_wasInMenuScene)
			{
				Log.LogInfo((object)"Returned to menu, saving data...");
				_staticSaveSystem?.Save();
				_gameplaySessionCharacter = null;
			}
			else if (!flag)
			{
				string currentCharacterName = GetCurrentCharacterName();
				if (!string.IsNullOrEmpty(currentCharacterName))
				{
					if (string.Equals(_gameplaySessionCharacter, currentCharacterName, StringComparison.Ordinal))
					{
						ManualLogSource log = Log;
						if (log != null)
						{
							log.LogDebug((object)("[SenpaisChest] Skip disk reload on scene '" + ((Scene)(ref scene)).name + "' — '" + currentCharacterName + "' already active"));
						}
					}
					else
					{
						_staticManager?.SetCharacterName(currentCharacterName);
						SmartChestSaveData data = _staticSaveSystem?.Load(currentCharacterName);
						_staticManager?.LoadData(data);
						_gameplaySessionCharacter = currentCharacterName;
						ManualLogSource log2 = Log;
						if (log2 != null)
						{
							log2.LogDebug((object)("[SenpaisChest] Loaded smart chest data from disk for '" + currentCharacterName + "' on scene load"));
						}
					}
				}
			}
			_wasInMenuScene = flag;
		}

		private void OnDestroy()
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)"Plugin OnDestroy called — static references preserved");
			}
			_staticSaveSystem?.Save();
		}

		private void OnApplicationQuit()
		{
			_applicationQuitting = true;
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)"Application quitting — saving data");
			}
			_staticSaveSystem?.Save();
		}

		private static bool IsDiscardedSceneSuppressed(Scene scene)
		{
			if (!((Scene)(ref scene)).IsValid())
			{
				return false;
			}
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			int[] array = null;
			int num = 0;
			foreach (KeyValuePair<int, float> item in _sceneDiscardSuppressByHandle)
			{
				if (!(item.Value > realtimeSinceStartup))
				{
					if (array == null)
					{
						array = new int[_sceneDiscardSuppressByHandle.Count];
					}
					array[num++] = item.Key;
				}
			}
			for (int i = 0; i < num; i++)
			{
				_sceneDiscardSuppressByHandle.Remove(array[i]);
			}
			float value;
			return _sceneDiscardSuppressByHandle.TryGetValue(((Scene)(ref scene)).handle, out value) && realtimeSinceStartup < value;
		}

		private static void OnActiveSceneChanged(Scene previous, Scene next)
		{
			if (((Scene)(ref previous)).IsValid())
			{
				_sceneDiscardSuppressByHandle[((Scene)(ref previous)).handle] = Time.realtimeSinceStartup + 20f;
			}
		}

		internal static SmartChestManager GetManager()
		{
			return _staticManager;
		}

		internal static SmartChestSaveSystem GetSaveSystem()
		{
			return _staticSaveSystem;
		}

		internal static string GetCurrentCharacterName()
		{
			try
			{
				CharacterData currentCharacter = GameSave.CurrentCharacter;
				return (currentCharacter != null) ? currentCharacter.characterName : null;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogDebug((object)("[SenpaisChest] GetCurrentCharacterName: " + ex.Message));
				}
				return null;
			}
		}

		internal static SmartChestUI GetUI()
		{
			return _staticUI;
		}

		internal static SmartChestConfig GetConfig()
		{
			return _staticConfig;
		}

		internal static MuseumTodoIntegration GetMuseumTodoIntegration()
		{
			return _museumTodoIntegration;
		}
	}
	public class SmartChestPersistentRunner : MonoBehaviour
	{
		private float _scanTimer;

		private float _autoSaveTimer;

		private float _chestLabelScanTimer;

		private const float AUTO_SAVE_INTERVAL = 300f;

		private const float CHEST_LABEL_SCAN_INTERVAL = 2f;

		private int _lastCountdownSecond = -1;

		private void Update()
		{
			Plugin.ProcessPendingChestButton();
			SmartChestConfig config = Plugin.GetConfig();
			if (config != null && config.EnableChestLabels.Value)
			{
				_chestLabelScanTimer += Time.unscaledDeltaTime;
				if (_chestLabelScanTimer >= 2f)
				{
					_chestLabelScanTimer = 0f;
					Chest[] array = Object.FindObjectsOfType<Chest>();
					Chest[] array2 = array;
					foreach (Chest val in array2)
					{
						if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).gameObject != (Object)null)
						{
							ChestLabelPatch.EnsureLabel(val);
						}
					}
				}
			}
			SmartChestManager manager = Plugin.GetManager();
			if (config == null || manager == null)
			{
				return;
			}
			float unscaledDeltaTime = Time.unscaledDeltaTime;
			float scanInterval = config.GetScanInterval();
			_scanTimer += unscaledDeltaTime;
			float num = scanInterval - _scanTimer;
			int num2 = (int)Math.Ceiling(num);
			if (num2 >= 1 && num2 <= 10 && num2 != _lastCountdownSecond)
			{
				_lastCountdownSecond = num2;
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"[Scan] Next scan in {num2}...");
				}
			}
			if (_scanTimer >= scanInterval)
			{
				_scanTimer = 0f;
				_lastCountdownSecond = -1;
				try
				{
					manager.ExecuteScan(config.MaxItemsPerScan.Value, config.EnableNotifications.Value);
					Plugin.GetMuseumTodoIntegration()?.OnScanComplete();
				}
				catch (Exception arg)
				{
					ManualLogSource log2 = Plugin.Log;
					if (log2 != null)
					{
						log2.LogError((object)$"Error during scan: {arg}");
					}
				}
			}
			_autoSaveTimer += unscaledDeltaTime;
			if (_autoSaveTimer >= 300f)
			{
				_autoSaveTimer = 0f;
				if (manager.IsDirty)
				{
					Plugin.GetSaveSystem()?.Save();
				}
			}
			DetectHotkey(config);
		}

		private void DetectHotkey(SmartChestConfig config)
		{
			//IL_0016: 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_0022: Unknown result type (might be due to invalid IL or missing references)
			if (TextInputFocusGuard.ShouldDeferModHotkeys(Plugin.Log))
			{
				return;
			}
			KeyCode staticToggleKey = SmartChestConfig.StaticToggleKey;
			bool staticRequireCtrl = SmartChestConfig.StaticRequireCtrl;
			if (Input.GetKeyDown(staticToggleKey) && (!staticRequireCtrl || Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305)))
			{
				SmartChestUI uI = Plugin.GetUI();
				if (!((Object)(object)uI == (Object)null) && (Object)(object)Plugin.CurrentInteractingChest != (Object)null)
				{
					uI.ToggleForChest(Plugin.CurrentInteractingChest);
				}
			}
		}

		private void OnDestroy()
		{
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogWarning((object)"[PersistentRunner] OnDestroy called — this should NOT happen!");
			}
		}
	}
	public static class PluginInfo
	{
		public const string PLUGIN_GUID = "com.azraelgodking.senpaischest";

		public const string PLUGIN_NAME = "Senpai's Chest";

		public const string PLUGIN_VERSION = "2.2.4";
	}
}
namespace SenpaisChest.UI
{
	[DefaultExecutionOrder(-30000)]
	public class SmartChestUI : MonoBehaviour
	{
		private const string PAUSE_ID = "SenpaisChest_Config";

		private SmartChestManager _manager;

		private bool _isVisible;

		private Chest _currentChest;

		private SmartChestData _currentData;

		private string _chestId;

		private float _scale = 1f;

		private const float BASE_WINDOW_WIDTH = 420f;

		private const float BASE_WINDOW_HEIGHT = 500f;

		private const float BASE_GROUPS_WIDTH = 400f;

		private const float BASE_GROUPS_HEIGHT = 450f;

		private Rect _windowRect = new Rect(100f, 100f, 420f, 500f);

		private GameObject _notePanelRoot;

		private Rect _noteRect;

		private bool _noteRectDirty = true;

		private float _contentHeight = 500f;

		private int _selectedRuleType;

		private string _itemIdInput = "";

		private int _selectedCategory;

		private int _selectedItemType;

		private int _selectedProperty;

		private int _selectedGroup;

		private string _lastSearchQuery = "";

		private List<KeyValuePair<int, string>> _searchResults = new List<KeyValuePair<int, string>>();

		private Vector2 _searchScrollPos;

		private int _selectedItemId = -1;

		private string _selectedItemName = "";

		private bool _groupsWindowVisible;

		private Rect _groupsWindowRect;

		private ItemGroup _editingGroup;

		private string _newGroupName = "";

		private string _groupItemSearch = "";

		private string _groupItemSearchLast = "";

		private List<KeyValuePair<int, string>> _groupSearchResults = new List<KeyValuePair<int, string>>();

		private Vector2 _groupSearchScroll;

		private Vector2 _groupListScroll;

		private Vector2 _groupItemsScroll;

		private static readonly string[] RuleTypeNames = new string[5] { "By Item", "By Category", "By Item Type", "By Property", "By Group" };

		private static readonly string[] BaseCategoryNames = new string[6] { "Equip", "Use", "Craftable", "Monster", "Furniture", "Quest" };

		private static readonly string[] CategoryNamesWithMuseum = new string[7] { "Equip", "Use", "Craftable", "Monster", "Furniture", "Quest", "Undonated Items" };

		private static readonly string[] ItemTypeNames = new string[9] { "Normal", "Armor", "Food", "Fish", "Crop", "WateringCan", "Animal", "Pet", "Tool" };

		private static readonly string[] PropertyNames = new string[8] { "isGem", "isForageable", "isAnimalProduct", "isMeal", "isFruit", "isArtisanryItem", "isPotion", "isNotDonated" };

		private static readonly string[] PropertyDisplayNames = new string[8] { "Gems", "Forageables", "Animal Products", "Meals", "Fruits", "Artisanry Items", "Potions", "Museum (Not Donated)" };

		internal const string SearchFieldControlName = "SmartChestItemSearch";

		internal const string GroupSearchFieldControlName = "SmartChestGroupItemSearch";

		private readonly Color _bgDark = new Color(0.15f, 0.16f, 0.24f, 1f);

		private readonly Color _borderGold = new Color(0.75f, 0.65f, 0.3f, 1f);

		private readonly Color _goldText = new Color(0.95f, 0.85f, 0.35f, 1f);

		private readonly Color _whiteText = new Color(0.95f, 0.95f, 0.95f, 1f);

		private readonly Color _dimText = new Color(0.6f, 0.6f, 0.7f, 1f);

		private readonly Color _greenActive = new Color(0.2f, 0.55f, 0.45f, 1f);

		private readonly Color _greenHover = new Color(0.25f, 0.65f, 0.52f, 1f);

		private readonly Color _greenBright = new Color(0.3f, 0.7f, 0.55f, 1f);

		private readonly Color _redDanger = new Color(0.75f, 0.2f, 0.2f, 1f);

		private readonly Color _redHover = new Color(0.85f, 0.28f, 0.28f, 1f);

		private readonly Color _btnInactive = new Color(0.22f, 0.24f, 0.34f, 1f);

		private readonly Color _btnHover = new Color(0.3f, 0.32f, 0.44f, 1f);

		private readonly Color _ruleBoxColor = new Color(0.18f, 0.19f, 0.28f, 1f);

		private readonly Color _fieldBg = new Color(0.12f, 0.13f, 0.22f, 1f);

		private readonly Color _museumHighlight = new Color(0.35f, 0.65f, 0.85f, 1f);

		private readonly Color _parchmentLight = new Color(0.96f, 0.93f, 0.86f, 0.98f);

		private readonly Color _parchment = new Color(0.92f, 0.87f, 0.78f, 0.97f);

		private readonly Color _parchmentDark = new Color(0.85f, 0.78f, 0.65f, 0.95f);

		private readonly Color _woodDark = new Color(0.35f, 0.25f, 0.15f);

		private readonly Color _woodMedium = new Color(0.5f, 0.38f, 0.25f);

		private readonly Color _woodLight = new Color(0.65f, 0.52f, 0.38f);

		private readonly Color _goldPale = new Color(0.92f, 0.82f, 0.55f);

		private readonly Color _goldRich = new Color(0.72f, 0.55f, 0.2f);

		private readonly Color _borderWood = new Color(0.45f, 0.35f, 0.22f, 0.9f);

		private readonly Color _chestTextDark = new Color(0.08f, 0.06f, 0.05f, 1f);

		private readonly Color _chestTextDim = new Color(0.14f, 0.11f, 0.09f, 1f);

		private readonly Color _crimsonTitle = new Color(0.52f, 0.18f, 0.12f, 1f);

		private readonly Color _crimsonTitleLight = new Color(0.58f, 0.22f, 0.16f, 1f);

		private readonly Color _innerBorderCrimson = new Color(0.42f, 0.18f, 0.14f, 1f);

		private Texture2D _solidBg;

		private Texture2D _windowBg;

		private Texture2D _ruleBg;

		private Texture2D _btnInactiveTex;

		private Texture2D _btnHoverTex;

		private Texture2D _btnActiveTex;

		private Texture2D _btnActiveHoverTex;

		private Texture2D _redBtnTex;

		private Texture2D _redBtnHoverTex;

		private Texture2D _greenBtnTex;

		private Texture2D _greenBtnHoverTex;

		private Texture2D _closeBtnTex;

		private Texture2D _closeBtnHoverTex;

		private Texture2D _fieldBgTex;

		private Texture2D _chestParchmentBg;

		private Texture2D _chestWoodBorderTex;

		private Texture2D _chestRuleBoxTex;

		private Texture2D _chestSelectorTex;

		private Texture2D _chestSelectorHoverTex;

		private Texture2D _chestSelectorActiveTex;

		private Texture2D _chestAddBtnTex;

		private Texture2D _chestAddBtnHoverTex;

		private Texture2D _chestWoodBtnTex;

		private Texture2D _chestWoodBtnHoverTex;

		private Texture2D _chestDangerBtnTex;

		private Texture2D _chestDangerBtnHoverTex;

		private Texture2D _chestFieldBgTex;

		private Texture2D _chestGoldLineTex;

		private Texture2D _noteBannerBg;

		private Texture2D _noteBannerBorderTex;

		private Texture2D _configTitleBarTex;

		private Texture2D _configContentBg;

		private Texture2D _configGoldSeparatorTex;

		private Texture2D _configSectionHeaderTex;

		private Texture2D _configSearchFieldTex;

		private Texture2D _configRemoveBtnTex;

		private Texture2D _configRemoveBtnHoverTex;

		private Texture2D _configCloseBtnTex;

		private Texture2D _configCloseBtnHoverTex;

		private Texture2D _configWindowBg;

		private Texture2D _configInnerBorderTex;

		private GUIStyle _windowStyle;

		private GUIStyle _titleStyle;

		private GUIStyle _chestTitleStyle;

		private GUIStyle _chestLabelStyle;

		private GUIStyle _chestLabelBoldStyle;

		private GUIStyle _chestLabelDimStyle;

		private GUIStyle _chestSectionHeaderStyle;

		private GUIStyle _chestToggleStyle;

		private GUIStyle _sectionHeaderStyle;

		private GUIStyle _labelStyle;

		private GUIStyle _labelBoldStyle;

		private GUIStyle _labelDimStyle;

		private GUIStyle _ruleBoxStyle;

		private GUIStyle _ruleTextStyle;

		private GUIStyle _removeRuleBtnStyle;

		private GUIStyle _closeButtonStyle;

		private GUIStyle _toggleStyle;

		private GUIStyle _textFieldStyle;

		private GUIStyle _selectorStyle;

		private GUIStyle _selectorActiveStyle;

		private GUIStyle _addButtonStyle;

		private GUIStyle _dangerButtonStyle;

		private GUIStyle _closeBottomButtonStyle;

		private GUIStyle _searchResultStyle;

		private GUIStyle _searchResultSelectedStyle;

		private GUIStyle _chestRuleBoxStyle;

		private GUIStyle _chestRuleTextStyle;

		private GUIStyle _chestSelectorStyle;

		private GUIStyle _chestSelectorActiveStyle;

		private GUIStyle _chestAddButtonStyle;

		private GUIStyle _chestDangerButtonStyle;

		private GUIStyle _chestCloseButtonStyle;

		private GUIStyle _chestSearchFieldStyle;

		private GUIStyle _chestRemoveRuleBtnStyle;

		private GUIStyle _chestSearchResultStyle;

		private GUIStyle _chestSearchResultSelectedStyle;

		private GUIStyle _noteBannerStyle;

		private GUIStyle _configTitleStyle;

		private GUIStyle _configSectionHeaderBoxStyle;

		private GUIStyle _configSearchFieldStyle;

		private GUIStyle _configRemoveButtonStyle;

		private GUIStyle _configCloseBottomStyle;

		private GUIStyle _configWindowStyle;

		private bool _stylesInitialized;

		private float WindowWidth => 420f * _scale;

		private float WindowHeight => 500f * _scale;

		private float GroupsWindowWidth => 400f * _scale;

		private float GroupsWindowHeight => 450f * _scale;

		public bool IsVisible => _isVisible;

		public bool IsEmbedded => false;

		private float Scaled(float value)
		{
			return value * _scale;
		}

		private int ScaledFont(int baseSize)
		{
			return Mathf.Max(8, Mathf.RoundToInt((float)baseSize * _scale));
		}

		private int ScaledInt(float value)
		{
			return Mathf.RoundToInt(value * _scale);
		}

		internal static bool ShouldBlockGameInput(SmartChestUI ui)
		{
			if ((Object)(object)ui == (Object)null || !ui.IsVisible)
			{
				return false;
			}
			string nameOfFocusedControl = GUI.GetNameOfFocusedControl();
			return nameOfFocusedControl == "SmartChestItemSearch" || nameOfFocusedControl == "SmartChestGroupItemSearch";
		}

		public void Initialize(SmartChestManager manager)
		{
			//IL_001f: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			_manager = manager;
			_windowRect = new Rect(100f, 100f, WindowWidth, WindowHeight);
			_groupsWindowRect = new Rect(150f, 150f, GroupsWindowWidth, GroupsWindowHeight);
		}

		public void SetScale(float scale)
		{
			_scale = Mathf.Clamp(scale, 0.5f, 2.5f);
			_stylesInitialized = false;
			((Rect)(ref _windowRect)).width = WindowWidth;
			((Rect)(ref _windowRect)).height = WindowHeight;
			((Rect)(ref _groupsWindowRect)).width = GroupsWindowWidth;
			((Rect)(ref _groupsWindowRect)).height = GroupsWindowHeight;
		}

		public void Show()
		{
			_isVisible = true;
		}

		public void Hide()
		{
			_isVisible = false;
			BlockGameInput(block: false);
			Chest currentChest = _currentChest;
			_currentChest = null;
			_currentData = null;
			_notePanelRoot = null;
			_noteRectDirty = true;
			Plugin.CurrentInteractingChest = null;
			SaveIfDirty();
			if (!((Object)(object)currentChest != (Object)null))
			{
				return;
			}
			try
			{
				currentChest.EndInteract(0);
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)("[SmartChestUI] EndInteract on close: " + ex.Message));
				}
			}
		}

		public void HideConfig()
		{
			SaveIfDirty();
			_isVisible = false;
			_groupsWindowVisible = false;
			BlockGameInput(block: false);
		}

		private void BlockGameInput(bool block)
		{
			try
			{
				if ((Object)(object)Player.Instance != (Object)null)
				{
					if (block)
					{
						Player.Instance.AddPauseObject("SenpaisChest_Config");
					}
					else
					{
						Player.Instance.RemovePauseObject("SenpaisChest_Config");
					}
				}
				Type type = Type.GetType("PlayerInput, Assembly-CSharp");
				if (type != null)
				{
					type.GetMethod(block ? "DisableInput" : "EnableInput", BindingFlags.Static | BindingFlags.Public, null, new Type[1] { typeof(string) }, null)?.Invoke(null, new object[1] { "SenpaisChest_Config" });
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)("[SmartChestUI] BlockGameInput failed: " + ex.Message));
				}
			}
		}

		public void Toggle()
		{
			if (_isVisible)
			{
				Hide();
			}
			else
			{
				Show();
			}
		}

		public void ToggleForChest(Chest chest)
		{
			//IL_00c3: 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)
			if (_isVisible && (Object)(object)_currentChest == (Object)(object)chest)
			{
				HideConfig();
				return;
			}
			_currentChest = chest;
			_chestId = SmartChestManager.GetChestId(chest);
			if (string.IsNullOrEmpty(_chestId))
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"Cannot configure chest: no valid ID");
				}
				return;
			}
			string chestName = GetChestName(chest);
			_currentData = _manager.GetOrCreateSmartChest(_chestId, chestName);
			_selectedRuleType = 0;
			_itemIdInput = "";
			_lastSearchQuery = "";
			_searchResults.Clear();
			_selectedItemId = -1;
			_selectedItemName = "";
			_searchScrollPos = Vector2.zero;
			_selectedCategory = 0;
			_selectedItemType = 0;
			_selectedProperty = 0;
			_isVisible = true;
			BlockGameInput(block: true);
			PositionWindowNextToChestPanel();
		}

		public void ShowNoteForChest(Chest chest, GameObject panelRoot)
		{
			_currentChest = chest;
			_chestId = SmartChestManager.GetChestId(chest);
			if (string.IsNullOrEmpty(_chestId))
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)"[SmartChestUI] Cannot show note: no valid chest ID");
				}
				return;
			}
			_currentData = null;
			_notePanelRoot = panelRoot;
			_noteRectDirty = true;
			_isVisible = false;
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogDebug((object)$"[SmartChestUI] ShowNoteForChest: chest={(Object)(object)chest != (Object)null}, panelRoot={(Object)(object)panelRoot != (Object)null}");
			}
		}

		private void PositionWindowNextToChestPanel()
		{
			if (!((Object)(object)_currentChest == (Object)null))
			{
				float num = Scaled(8f);
				float height = Mathf.Min(Scaled(400f), (float)Screen.height - num);
				((Rect)(ref _windowRect)).width = WindowWidth;
				((Rect)(ref _windowRect)).height = height;
				((Rect)(ref _windowRect)).x = Mathf.Clamp(((float)Screen.width - ((Rect)(ref _windowRect)).width) * 0.5f, 0f, (float)Screen.width - ((Rect)(ref _windowRect)).width);
				((Rect)(ref _windowRect)).y = num;
			}
		}

		private string GetChestName(Chest chest)
		{
			return SmartChestManager.GetChestName(chest);
		}

		private void OnGUI()
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Invalid comparison between Unknown and I4
			//IL_020d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Expected O, but got Unknown
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Expected O, but got Unknown
			//IL_026a: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: 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_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			if (!_stylesInitialized)
			{
				InitializeStyles();
			}
			if ((Object)(object)_notePanelRoot != (Object)null && !_isVisible)
			{
				if (!_notePanelRoot.activeInHierarchy)
				{
					_notePanelRoot = null;
					return;
				}
				if (_noteRectDirty || (int)Event.current.type == 8)
				{
					_noteRect = GetScreenRectFromTransform(_notePanelRoot.transform);
					_noteRectDirty = false;
				}
				Rect val = _noteRect;
				if (((Rect)(ref val)).width <= 0f || ((Rect)(ref val)).height <= 0f)
				{
					((Rect)(ref val))..ctor(((float)Screen.width - Scaled(340f)) * 0.5f, Scaled(8f), Scaled(340f), Scaled(34f));
				}
				val = ClampRectToScreen(val);
				GUI.BeginGroup(val);
				DrawNoteContent(((Rect)(ref val)).width, ((Rect)(ref val)).height);
				GUI.EndGroup();
			}
			else if (_isVisible && _currentData != null)
			{
				float num = (float)Screen.height - Scaled(40f);
				((Rect)(ref _windowRect)).width = WindowWidth;
				((Rect)(ref _windowRect)).height = Mathf.Clamp(_contentHeight, Scaled(300f), num);
				((Rect)(ref _windowRect)).x = Mathf.Clamp(((Rect)(ref _windowRect)).x, 0f, (float)Screen.width - ((Rect)(ref _windowRect)).width);
				((Rect)(ref _windowRect)).y = Mathf.Clamp(((Rect)(ref _windowRect)).y, 0f, (float)Screen.height - ((Rect)(ref _windowRect)).height);
				_windowRect = GUI.Window("com.azraelgodking.senpaischest".GetHashCode(), _windowRect, new WindowFunction(DrawWindow), "", _configWindowStyle);
				if (_groupsWindowVisible)
				{
					_groupsWindowRect = GUI.Window("com.azraelgodking.senpaischest".GetHashCode() + 1, _groupsWindowRect, new WindowFunction(DrawGroupsWindow), "Manage Groups", _configWindowStyle);
				}
			}
		}

		private static Rect GetScreenRectFromTransform(Transform transform)
		{
			//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_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Invalid comparison between Unknown and I4
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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)
			RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			if ((Object)(object)val == (Object)null)
			{
				return new Rect(0f, 0f, 400f, 400f);
			}
			Canvas componentInParent = ((Component)val).GetComponentInParent<Canvas>();
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			val.GetWorldCorners(array);
			Vector2 val2 = default(Vector2);
			Vector2 val3 = default(Vector2);
			if ((Object)(object)componentInParent != (Object)null && (int)componentInParent.renderMode == 0)
			{
				((Vector2)(ref val2))..ctor(array[0].x, array[0].y);
				((Vector2)(ref val3))..ctor(array[2].x, array[2].y);
			}
			else
			{
				Camera val4 = (((Object)(object)componentInParent != (Object)null) ? componentInParent.worldCamera : Camera.main);
				val2 = RectTransformUtility.WorldToScreenPoint(val4, array[0]);
				val3 = RectTransformUtility.WorldToScreenPoint(val4, array[2]);
			}
			float x = val2.x;
			float num = (float)Screen.height - val3.y;
			float num2 = val3.x - val2.x;
			float num3 = val3.y - val2.y;
			Rect result = default(Rect);
			((Rect)(ref result))..ctor(x, num, num2, num3);
			return result;
		}

		private static Rect ClampRectToScreen(Rect rect)
		{
			//IL_005f: 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_0068: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Min(((Rect)(ref rect)).width, (float)Screen.width);
			float num2 = Mathf.Min(((Rect)(ref rect)).height, (float)Screen.height);
			float num3 = Mathf.Clamp(((Rect)(ref rect)).x, 0f, (float)Screen.width - num);
			float num4 = Mathf.Clamp(((Rect)(ref rect)).y, 0f, (float)Screen.height - num2);
			return new Rect(num3, num4, num, num2);
		}

		private void DrawWindow(int windowId)
		{
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			DrawConfigContent(new Rect(0f, 0f, ((Rect)(ref _windowRect)).width, ((Rect)(ref _windowRect)).height), withWindowChrome: true);
		}

		private void DrawConfigContent(Rect rect, bool withWindowChrome)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Invalid comparison between Unknown and I4
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_026b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_039c: Unknown result type (might be due to invalid IL or missing references)
			//IL_042f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0434: Unknown result type (might be due to invalid IL or missing references)
			//IL_0436: Unknown result type (might be due to invalid IL or missing references)
			//IL_067d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0682: Unknown result type (might be due to invalid IL or missing references)
			//IL_0684: Unknown result type (might be due to invalid IL or missing references)
			//IL_06fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0701: Unknown result type (might be due to invalid IL or missing references)
			//IL_087f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0884: Unknown result type (might be due to invalid IL or missing references)
			//IL_0886: Unknown result type (might be due to invalid IL or missing references)
			//IL_08e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_08e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_08eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b10: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b16: Invalid comparison between Unknown and I4
			//IL_0ab3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ab9: Invalid comparison between Unknown and I4
			//IL_09ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_09cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_09d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b1d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0b23: Invalid comparison between Unknown and I4
			//IL_0aff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ac2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0ac7: Unknown result type (might be due to invalid IL or missing references)
			if ((int)Event.current.type == 4 && (int)Event.current.keyCode == 27)
			{
				Event.current.Use();
				HideConfig();
				return;
			}
			bool flag = !withWindowChrome;
			bool flag2 = withWindowChrome;
			if (withWindowChrome)
			{
				float num = Scaled(36f);
				float num2 = Scaled(5f);
				float num3 = Scaled(1f);
				if ((Object)(object)_configInnerBorderTex != (Object)null)
				{
					float num4 = num2;
					float num5 = num2;
					float num6 = ((Rect)(ref rect)).width - num2 * 2f;
					float num7 = ((Rect)(ref rect)).height - num2 * 2f;
					GUI.DrawTexture(new Rect(num4, num5, num6, num3), (Texture)(object)_configInnerBorderTex);
					GUI.DrawTexture(new Rect(num4, num5 + num7 - num3, num6, num3), (Texture)(object)_configInnerBorderTex);
					GUI.DrawTexture(new Rect(num4, num5, num3, num7), (Texture)(object)_configInnerBorderTex);
					GUI.DrawTexture(new Rect(num4 + num6 - num3, num5, num3, num7), (Texture)(object)_configInnerBorderTex);
				}
				if ((Object)(object)_configTitleBarTex != (Object)null)
				{
					GUI.DrawTexture(new Rect(0f, 0f, ((Rect)(ref rect)).width, num), (Texture)(object)_configTitleBarTex);
				}
				GUILayout.BeginArea(new Rect(0f, 0f, ((Rect)(ref rect)).width, num));
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.FlexibleSpace();
				GUILayout.Label("Senpai's Chest Config", _configTitleStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				GUILayout.FlexibleSpace();
				if (GUILayout.Button("X", _closeButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
				{
					GUILayout.Width(Scaled(28f)),
					GUILayout.Height(Scaled(24f))
				}))
				{
					HideConfig();
				}
				GUILayout.Space(Scaled(4f));
				GUILayout.EndHorizontal();
				GUILayout.EndArea();
				GUILayout.Space(num + Scaled(2f));
				if ((Object)(object)_configGoldSeparatorTex != (Object)null)
				{
					Rect rect2 = GUILayoutUtility.GetRect(((Rect)(ref rect)).width - Scaled(24f), Scaled(2f));
					GUI.DrawTexture(rect2, (Texture)(object)_configGoldSeparatorTex);
				}
				GUILayout.Space(Scaled(8f));
			}
			if (withWindowChrome)
			{
				GUILayout.Space(4f);
			}
			float num8 = (flag ? ((((Rect)(ref rect)).width - 8f) / 2f) : 0f);
			if (flag)
			{
				GUILayout.BeginHorizontal((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(((Rect)(ref rect)).width) });
				GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num8) });
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			bool flag3 = GUILayout.Toggle(_currentData.IsEnabled, " Smart Chest Enabled", flag2 ? _chestToggleStyle : _toggleStyle, Array.Empty<GUILayoutOption>());
			if (flag3 != _currentData.IsEnabled)
			{
				_currentData.IsEnabled = flag3;
				_manager.MarkDirty();
				SaveIfDirty();
			}
			GUILayout.EndHorizontal();
			if (flag2 && (Object)(object)_configGoldSeparatorTex != (Object)null)
			{
				Rect rect3 = GUILayoutUtility.GetRect(((Rect)(ref rect)).width - 24f, 2f);
				GUI.DrawTexture(rect3, (Texture)(object)_configGoldSeparatorTex);
				GUILayout.Space(6f);
			}
			else
			{
				GUILayout.Space((float)(flag ? 4 : 8));
			}
			GUIStyle val = (flag2 ? _configSectionHeaderBoxStyle : (flag ? _chestSectionHeaderStyle : _sectionHeaderStyle));
			GUILayout.Label("Item Rules", val, Array.Empty<GUILayoutOption>());
			GUILayout.Space((float)(flag ? 2 : 4));
			if (flag2 && (Object)(object)_configGoldSeparatorTex != (Object)null)
			{
				Rect rect4 = GUILayoutUtility.GetRect(((Rect)(ref rect)).width - 24f, 2f);
				GUI.DrawTexture(rect4, (Texture)(object)_configGoldSeparatorTex);
				GUILayout.Space(4f);
			}
			if (_currentData.Rules.Count == 0)
			{
				GUILayout.Label("  No rules configured. Add rules below.", flag2 ? _chestLabelDimStyle : (flag ? _chestLabelDimStyle : _labelDimStyle), Array.Empty<GUILayoutOption>());
			}
			else
			{
				float num9 = (flag ? 24f : 36f);
				float num10 = (flag ? 100f : 180f);
				float num11 = Mathf.Min((float)_currentData.Rules.Count * num9, num10);
				GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(num11) });
				int num12 = -1;
				for (int i = 0; i < _currentData.Rules.Count; i++)
				{
					GUIStyle val2 = (flag2 ? _chestRuleBoxStyle : (flag ? _chestRuleBoxStyle : _ruleBoxStyle));
					GUIStyle val3 = (flag2 ? _chestRuleTextStyle : (flag ? _chestRuleTextStyle : _ruleTextStyle));
					GUIStyle val4 = (flag2 ? _chestRemoveRuleBtnStyle : (flag ? _chestRemoveRuleBtnStyle : _removeRuleBtnStyle));
					GUILayout.BeginHorizontal(val2, Array.Empty<GUILayoutOption>());
					GUILayout.Label($"{i + 1}. {GetRuleDisplayText(_currentData.Rules[i])}", val3, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
					if (GUILayout.Button("X", val4, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.Width(26f),
						GUILayout.Height(22f)
					}))
					{
						num12 = i;
					}
					GUILayout.EndHorizontal();
					GUILayout.Space((float)(flag ? 1 : 2));
				}
				GUILayout.EndVertical();
				if (num12 >= 0)
				{
					_currentData.Rules.RemoveAt(num12);
					_manager.MarkDirty();
					SaveIfDirty();
				}
			}
			if (flag2 && (Object)(object)_configGoldSeparatorTex != (Object)null)
			{
				Rect rect5 = GUILayoutUtility.GetRect(((Rect)(ref rect)).width - 24f, 2f);
				GUI.DrawTexture(rect5, (Texture)(object)_configGoldSeparatorTex);
				GUILayout.Space(8f);
			}
			else
			{
				GUILayout.Space((float)(flag ? 4 : 10));
			}
			GUILayout.Label("Add New Rule", val, Array.Empty<GUILayoutOption>());
			GUILayout.Space((float)(flag ? 2 : 6));
			if (flag2 && (Object)(object)_configGoldSeparatorTex != (Object)null)
			{
				Rect rect6 = GUILayoutUtility.GetRect(((Rect)(ref rect)).width - 24f, 2f);
				GUI.DrawTexture(rect6, (Texture)(object)_configGoldSeparatorTex);
				GUILayout.Space(4f);
			}
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			DrawSelectorButton(0, flag2 || flag, GUILayout.Height((float)((flag2 || flag) ? 24 : 28)));
			DrawSelectorButton(1, flag2 || flag, GUILayout.Height((float)((flag2 || flag) ? 24 : 28)));
			DrawSelectorButton(2, flag2 || flag, GUILayout.Height((float)((flag2 || flag) ? 24 : 28)));
			GUILayout.EndHorizontal();
			GUILayout.Space((float)(flag ? 1 : 2));
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			DrawSelectorButton(3, flag2 || flag, GUILayout.Height((float)((flag2 || flag) ? 24 : 28)));
			DrawSelectorButton(4, flag2 || flag, GUILayout.Height((float)((flag2 || flag) ? 24 : 28)));
			if (GUILayout.Button("Manage Groups", flag2 ? _configCloseBottomStyle : _closeBottomButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height((float)((flag2 || flag) ? 22 : 26)) }))
			{
				_groupsWindowVisible = true;
			}
			GUILayout.EndHorizontal();
			GUILayout.Space((float)(flag ? 4 : 8));
			if (flag2 && (Object)(object)_configGoldSeparatorTex != (Object)null)
			{
				Rect rect7 = GUILayoutUtility.GetRect(((Rect)(ref rect)).width - 24f, 2f);
				GUI.DrawTexture(rect7, (Texture)(object)_configGoldSeparatorTex);
				GUILayout.Space(4f);
			}
			DrawRuleInput(flag2 || flag, flag2);
			GUILayout.Space((float)(flag ? 4 : 8));
			if (flag2 && (Object)(object)_configGoldSeparatorTex != (Object)null)
			{
				Rect rect8 = GUILayoutUtility.GetRect(((Rect)(ref rect)).width - 24f, 2f);
				GUI.DrawTexture(rect8, (Texture)(object)_configGoldSeparatorTex);
				GUILayout.Space(6f);
			}
			GUIStyle val5 = (flag2 ? _chestAddButtonStyle : (flag ? _chestAddButtonStyle : _addButtonStyle));
			if (GUILayout.Button("Add Rule", val5, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height((float)((flag2 || flag) ? 24 : 30)) }))
			{
				AddRule();
			}
			if (flag)
			{
				GUILayout.EndVertical();
				GUILayout.Space(8f);
				GUILayout.BeginVertical((GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(num8) });
				DrawEmbeddedRightColumn(flag);
				GUILayout.EndVertical();
				GUILayout.EndHorizontal();
			}
			else
			{
				if (flag2 && (Object)(object)_configGoldSeparatorTex != (Object)null)
				{
					Rect rect9 = GUILayoutUtility.GetRect(((Rect)(ref rect)).width - 24f, 2f);
					GUI.DrawTexture(rect9, (Texture)(object)_configGoldSeparatorTex);
					GUILayout.Space(8f);
				}
				else
				{
					GUILayout.Space(12f);
				}
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				if (GUILayout.Button("Remove Smart Chest", flag2 ? _configRemoveButtonStyle : _dangerButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }))
				{
					_manager.RemoveSmartChest(_chestId);
					SaveIfDirty();
					HideConfig();
				}
				GUILayout.Space(8f);
				if (GUILayout.Button("Close", flag2 ? _configCloseBottomStyle : _closeBottomButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(28f) }))
				{
					HideConfig();
				}
				GUILayout.EndHorizontal();
			}
			if (withWindowChrome)
			{
				if ((int)Event.current.type == 7)
				{
					Rect lastRect = GUILayoutUtility.GetLastRect();
					_contentHeight = ((Rect)(ref lastRect)).yMax + Scaled(24f);
				}
				GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref rect)).width, Scaled(28f)));
			}
			if ((int)Event.current.type == 4 && (int)Event.current.keyCode == 8)
			{
				Event.current.Use();
			}
		}

		private void DrawEmbeddedRightColumn(bool compact)
		{
			GUILayout.Space(4f);
			GUILayout.Label("Summary", _chestSectionHeaderStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			int valueOrDefault = (_currentData?.Rules?.Count).GetValueOrDefault();
			SmartChestData currentData = _currentData;
			string arg = ((currentData != null && currentData.IsEnabled) ? "Active" : "Disabled");
			GUILayout.BeginVertical(_chestRuleBoxStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label($"Rules: {valueOrDefault} | Status: {arg}", _chestLabelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			if (valueOrDefault > 0)
			{
				GUILayout.Label("Accepts:", _chestLabelBoldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				for (int i = 0; i < valueOrDefault; i++)
				{
					GUILayout.Label("  • " + GetRuleDisplayText(_currentData.Rules[i]), _chestLabelDimStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
				}
			}
			GUILayout.EndVertical();
			GUILayout.Space(4f);
			GUILayout.Label("Tips", _chestSectionHeaderStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			GUILayout.BeginVertical(_chestRuleBoxStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label("• Rules filter auto-sort. Multiple = AND.", _chestRuleTextStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			GUILayout.Label("• Transfer SAME/ALL applies rules.", _chestRuleTextStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			GUILayout.EndVertical();
			GUILayout.Space(8f);
			if (GUILayout.Button("Remove Smart Chest", _chestDangerButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Height(20f),
				GUILayout.ExpandWidth(true)
			}))
			{
				_manager.RemoveSmartChest(_chestId);
				SaveIfDirty();
				HideConfig();
			}
			GUILayout.Space(2f);
			if (GUILayout.Button("Close", _chestCloseButtonStyle, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Height(20f),
				GUILayout.ExpandWidth(true)
			}))
			{
				HideConfig();
			}
		}

		private void DrawGroupsWindow(int windowId)
		{
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_06e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Unknown result type (might be due to invalid IL or missing references)
			//IL_0368: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_054c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0564: Unknown result type (might be due to invalid IL or missing references)
			//IL_0569: Unknown result type (might be due to invalid IL or missing references)
			if (!_stylesInitialized)
			{
				InitializeStyles();
			}
			GUIStyle chestLabelBoldStyle = _chestLabelBoldStyle;
			GUIStyle chestLabelStyle = _chestLabelStyle;
			GUIStyle chestLabelDimStyle = _chestLabelDimStyle;
			GUILayout.Label("Create or edit groups. Use 'By Group' when adding rules to attach a group to a chest.", chestLabelDimStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			GUILayout.Space(6f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			_newGroupName = GUILayout.TextField(_newGroupName ?? "", _configSearchFieldStyle ?? _chestSearchFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true)