Decompiled source of HavenDevTools v1.0.4

HavenDevTools.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Cryptography;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using HavenDevTools.API;
using HavenDevTools.Config;
using HavenDevTools.Integrations;
using HavenDevTools.Services;
using HavenDevTools.UI;
using Microsoft.CodeAnalysis;
using SunhavenMods.Shared;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.SceneManagement;
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("HavenDevTools")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+54235fa387ce65f1ea7f743eb7e9b44371b337da")]
[assembly: AssemblyProduct("HavenDevTools")]
[assembly: AssemblyTitle("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);
			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 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;
			}
		}
	}
}
namespace HavenDevTools
{
	[BepInPlugin("com.azraelgodking.havendevtools", "Haven Dev Tools", "1.0.4")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : BaseUnityPlugin
	{
		private static ItemInspector _staticItemInspector;

		private static CurrencyTracker _staticCurrencyTracker;

		private static BundleInspector _staticBundleInspector;

		private static RaceModifierTracker _staticRaceModifierTracker;

		private static DebugWindow _staticDebugWindow;

		private static DebugOverlay _staticDebugOverlay;

		private static CommandConsole _staticCommandConsole;

		private static LogViewerPanel _staticLogViewer;

		private static GameObject _persistentRunner;

		private static PersistentRunner _persistentRunnerComponent;

		internal static KeyCode StaticToggleKey = (KeyCode)292;

		internal static KeyCode StaticOverlayToggleKey = (KeyCode)287;

		private static readonly HashSet<string> _authorizedSteamIdHashes = new HashSet<string> { "Tr4eyf86yKRu6fhNQjQOrO/ZnwasQaY/fgKV0PcnoGA=" };

		private static bool _isAuthorized;

		private static string _currentSteamId;

		private static string _currentPlayerName;

		private Harmony _harmony;

		public static Plugin Instance { get; private set; }

		public static ManualLogSource Log { get; private set; }

		public static ConfigFile ConfigFile { get; private set; }

		public static bool HasTheVault { get; private set; }

		public static bool HasSMUT { get; private set; }

		public static bool HasHavensBirthright { get; private set; }

		public static bool HasSenpaisChest { get; private set; }

		public static bool HasBirthdayReminder { get; private set; }

		public static bool HasSunhavenTodo { get; private set; }

		public static bool HasHavensAlmanac { get; private set; }

		public static bool IsAuthorized => _isAuthorized;

		public static string CurrentPlayerName => _currentPlayerName;

		private void Awake()
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			ConfigFile = ((BaseUnityPlugin)this).Config;
			Log.LogInfo((object)"Loading Haven Dev Tools v1.0.4");
			try
			{
				ModConfig.Initialize(((BaseUnityPlugin)this).Config);
				StaticToggleKey = ModConfig.ToggleKey.Value;
				StaticOverlayToggleKey = ModConfig.OverlayToggleKey.Value;
				CreatePersistentRunner();
				DetectInstalledMods();
				_staticItemInspector = new ItemInspector();
				_staticCurrencyTracker = new CurrencyTracker();
				_staticBundleInspector = new BundleInspector();
				_staticRaceModifierTracker = new RaceModifierTracker();
				_staticCommandConsole = new CommandConsole();
				_staticLogViewer = new LogViewerPanel();
				CreateUIComponents();
				_harmony = new Harmony("com.azraelgodking.havendevtools");
				PatchPlayerInit();
				SceneManager.sceneLoaded += OnSceneLoaded;
				if (ModConfig.CheckForUpdates.Value)
				{
					VersionChecker.CheckForUpdate("com.azraelgodking.havendevtools", "1.0.4", Log, delegate(VersionChecker.VersionCheckResult result)
					{
						result.NotifyUpdateAvailable(Log);
					});
				}
				Log.LogInfo((object)"Haven Dev Tools loaded successfully!");
				Log.LogInfo((object)$"Press {ModConfig.ToggleKey.Value} to open the debug window (requires authorization)");
				Log.LogInfo((object)$"Press {ModConfig.OverlayToggleKey.Value} to toggle the overlay");
				Log.LogInfo((object)$"Detected mods - TheVault: {HasTheVault}, SMUT: {HasSMUT}, Birthright: {HasHavensBirthright}, SenpaisChest: {HasSenpaisChest}, Birthday: {HasBirthdayReminder}, Todo: {HasSunhavenTodo}, Almanac: {HasHavensAlmanac}");
			}
			catch (Exception arg)
			{
				Log.LogError((object)string.Format("Failed to load {0}: {1}", "Haven Dev Tools", arg));
			}
		}

		private void CreatePersistentRunner()
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Expected O, but got Unknown
			if (!((Object)(object)_persistentRunner != (Object)null) || !((Object)(object)_persistentRunnerComponent != (Object)null))
			{
				_persistentRunner = new GameObject("HavenDevTools_PersistentRunner");
				Object.DontDestroyOnLoad((Object)(object)_persistentRunner);
				((Object)_persistentRunner).hideFlags = (HideFlags)61;
				_persistentRunnerComponent = _persistentRunner.AddComponent<PersistentRunner>();
				Log.LogInfo((object)"[PersistentRunner] Created hidden persistent runner");
			}
		}

		private void CreateUIComponents()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			GameObject val = new GameObject("HavenDevTools_UI");
			Object.DontDestroyOnLoad((Object)(object)val);
			_staticDebugWindow = val.AddComponent<DebugWindow>();
			_staticDebugOverlay = val.AddComponent<DebugOverlay>();
			Log.LogInfo((object)"UI components created");
		}

		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_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Expected O, but got Unknown
			try
			{
				if ((Object)(object)_persistentRunner == (Object)null || (Object)(object)_persistentRunnerComponent == (Object)null)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogInfo((object)"[EnsureUI] Recreating PersistentRunner...");
					}
					_persistentRunner = new GameObject("HavenDevTools_PersistentRunner");
					Object.DontDestroyOnLoad((Object)(object)_persistentRunner);
					((Object)_persistentRunner).hideFlags = (HideFlags)61;
					_persistentRunnerComponent = _persistentRunner.AddComponent<PersistentRunner>();
					ManualLogSource log2 = Log;
					if (log2 != null)
					{
						log2.LogInfo((object)"[EnsureUI] PersistentRunner recreated");
					}
				}
				if ((Object)(object)_staticDebugWindow == (Object)null || (Object)(object)_staticDebugOverlay == (Object)null)
				{
					ManualLogSource log3 = Log;
					if (log3 != null)
					{
						log3.LogInfo((object)"[EnsureUI] Recreating UI components...");
					}
					GameObject val = new GameObject("HavenDevTools_UI");
					Object.DontDestroyOnLoad((Object)(object)val);
					_staticDebugWindow = val.AddComponent<DebugWindow>();
					_staticDebugOverlay = val.AddComponent<DebugOverlay>();
					ManualLogSource log4 = Log;
					if (log4 != null)
					{
						log4.LogInfo((object)"[EnsureUI] UI components recreated");
					}
				}
				if (_staticItemInspector == null)
				{
					_staticItemInspector = new ItemInspector();
				}
				if (_staticCurrencyTracker == null)
				{
					_staticCurrencyTracker = new CurrencyTracker();
				}
				if (_staticBundleInspector == null)
				{
					_staticBundleInspector = new BundleInspector();
				}
				if (_staticRaceModifierTracker == null)
				{
					_staticRaceModifierTracker = new RaceModifierTracker();
				}
				if (_staticCommandConsole == null)
				{
					_staticCommandConsole = new CommandConsole();
				}
				if (_staticLogViewer == null)
				{
					_staticLogViewer = new LogViewerPanel();
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log5 = Log;
				if (log5 != null)
				{
					log5.LogError((object)("[EnsureUI] Error recreating components: " + ex.Message));
				}
			}
		}

		private void DetectInstalledMods()
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				string name = assembly.GetName().Name;
				if (name == "TheVault")
				{
					HasTheVault = true;
				}
				if (name == "SunHavenMuseumUtilityTracker")
				{
					HasSMUT = true;
				}
				if (name == "HavensBirthright")
				{
					HasHavensBirthright = true;
				}
				if (name == "SenpaisChest")
				{
					HasSenpaisChest = true;
				}
				if (name == "BirthdayReminder")
				{
					HasBirthdayReminder = true;
				}
				if (name == "SunhavenTodo")
				{
					HasSunhavenTodo = true;
				}
				if (name == "HavensAlmanac")
				{
					HasHavensAlmanac = true;
				}
			}
			Log.LogInfo((object)$"Mod detection complete - TheVault: {HasTheVault}, SMUT: {HasSMUT}, Birthright: {HasHavensBirthright}, SenpaisChest: {HasSenpaisChest}, Birthday: {HasBirthdayReminder}, Todo: {HasSunhavenTodo}, Almanac: {HasHavensAlmanac}");
		}

		private void PatchPlayerInit()
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Expected O, but got Unknown
			try
			{
				Type typeFromHandle = typeof(Player);
				MethodInfo methodInfo = AccessTools.Method(typeFromHandle, "InitializeAsOwner", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					MethodInfo methodInfo2 = AccessTools.Method(typeof(Plugin), "OnPlayerInitialized", (Type[])null, (Type[])null);
					_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(methodInfo2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Log.LogInfo((object)"Patched Player.InitializeAsOwner");
				}
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Failed to patch player init: " + ex.Message));
			}
		}

		private static void OnPlayerInitialized()
		{
			ManualLogSource log = Log;
			if (log != null)
			{
				log.LogInfo((object)"[HavenDevTools] Player initialized, ensuring UI exists and checking authorization...");
			}
			EnsureUIComponentsExist();
			CheckAuthorization();
		}

		private void OnSceneLoaded(Scene scene, LoadSceneMode mode)
		{
			Log.LogInfo((object)("[SceneChange] Scene loaded: '" + ((Scene)(ref scene)).name + "'"));
			string text = ((Scene)(ref scene)).name.ToLowerInvariant();
			if (text.Contains("menu") || text.Contains("title"))
			{
				Log.LogInfo((object)("Menu scene detected: " + ((Scene)(ref scene)).name));
				_isAuthorized = false;
				_currentPlayerName = null;
			}
		}

		private void OnDestroy()
		{
			Log.LogWarning((object)"[CRITICAL] Plugin OnDestroy called!");
			SceneManager.sceneLoaded -= OnSceneLoaded;
		}

		private static void CheckAuthorization()
		{
			try
			{
				try
				{
					if ((Object)(object)Player.Instance != (Object)null)
					{
						PropertyInfo property = ((object)Player.Instance).GetType().GetProperty("PlayerName", BindingFlags.Instance | BindingFlags.Public);
						if (property != null)
						{
							_currentPlayerName = property.GetValue(Player.Instance) as string;
						}
						if (string.IsNullOrEmpty(_currentPlayerName))
						{
							_currentPlayerName = ((Object)Player.Instance).name;
						}
					}
				}
				catch (Exception ex)
				{
					ManualLogSource log = Log;
					if (log != null)
					{
						log.LogDebug((object)("[HavenDevTools] Player name fallback: " + ex.Message));
					}
					_currentPlayerName = "Unknown";
				}
				_currentSteamId = TryGetSteamId();
				if (!string.IsNullOrEmpty(_currentSteamId))
				{
					string text = ComputeHash(_currentSteamId);
					if (_authorizedSteamIdHashes.Contains(text))
					{
						ManualLogSource log2 = Log;
						if (log2 != null)
						{
							log2.LogInfo((object)"[HavenDevTools] Authorized via Steam ID");
						}
						_isAuthorized = true;
						return;
					}
					ManualLogSource log3 = Log;
					if (log3 != null)
					{
						log3.LogInfo((object)("[HavenDevTools] Steam ID hash not authorized: " + text));
					}
				}
				else
				{
					ManualLogSource log4 = Log;
					if (log4 != null)
					{
						log4.LogInfo((object)"[HavenDevTools] Could not retrieve Steam ID");
					}
				}
				ManualLogSource log5 = Log;
				if (log5 != null)
				{
					log5.LogInfo((object)"[HavenDevTools] Not authorized - Steam ID required");
				}
			}
			catch (Exception ex2)
			{
				ManualLogSource log6 = Log;
				if (log6 != null)
				{
					log6.LogError((object)("[HavenDevTools] Authorization error: " + ex2.Message));
				}
			}
		}

		private static string TryGetSteamId()
		{
			try
			{
				Assembly assembly = null;
				Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly2 in assemblies)
				{
					string name = assembly2.GetName().Name;
					if (name.Contains("rlabrecque") || name == "Steamworks.NET")
					{
						assembly = assembly2;
						break;
					}
				}
				if (assembly == null)
				{
					Assembly[] assemblies2 = AppDomain.CurrentDomain.GetAssemblies();
					foreach (Assembly assembly3 in assemblies2)
					{
						try
						{
							Type type = assembly3.GetType("Steamworks.SteamUser");
							if (type != null)
							{
								assembly = assembly3;
								break;
							}
						}
						catch (Exception ex)
						{
							ManualLogSource log = Log;
							if (log != null)
							{
								log.LogDebug((object)("[HavenDevTools] TryGetSteamId assembly search: " + ex.Message));
							}
						}
					}
				}
				if (assembly == null)
				{
					return null;
				}
				Type type2 = assembly.GetType("Steamworks.SteamUser");
				if (type2 == null)
				{
					return null;
				}
				MethodInfo method = type2.GetMethod("GetSteamID", BindingFlags.Static | BindingFlags.Public);
				if (method == null)
				{
					return null;
				}
				object obj = method.Invoke(null, null);
				if (obj == null)
				{
					return null;
				}
				string text = obj.ToString();
				if (string.IsNullOrEmpty(text) || text == "0" || text.Length < 10)
				{
					return null;
				}
				return text;
			}
			catch (Exception ex2)
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogDebug((object)("[HavenDevTools] TryGetSteamId: " + ex2.Message));
				}
				return null;
			}
		}

		private static string ComputeHash(string input)
		{
			using SHA256 sHA = SHA256.Create();
			byte[] inArray = sHA.ComputeHash(Encoding.UTF8.GetBytes(input));
			return Convert.ToBase64String(inArray);
		}

		public static string GenerateHash(string input)
		{
			return ComputeHash(input);
		}

		public static ItemInspector GetItemInspector()
		{
			return _staticItemInspector;
		}

		public static CurrencyTracker GetCurrencyTracker()
		{
			return _staticCurrencyTracker;
		}

		public static BundleInspector GetBundleInspector()
		{
			return _staticBundleInspector;
		}

		public static RaceModifierTracker GetRaceModifierTracker()
		{
			return _staticRaceModifierTracker;
		}

		public static DebugWindow GetDebugWindow()
		{
			return _staticDebugWindow;
		}

		public static DebugOverlay GetDebugOverlay()
		{
			return _staticDebugOverlay;
		}

		public static CommandConsole GetCommandConsole()
		{
			return _staticCommandConsole;
		}

		public static LogViewerPanel GetLogViewer()
		{
			return _staticLogViewer;
		}

		public static void ToggleDebugWindow()
		{
			if (_isAuthorized)
			{
				_staticDebugWindow?.Toggle();
				return;
			}
			CheckAuthorization();
			if (_isAuthorized)
			{
				_staticDebugWindow?.Toggle();
			}
		}

		public static void ToggleDebugOverlay()
		{
			if (_isAuthorized)
			{
				_staticDebugOverlay?.Toggle();
			}
		}
	}
	public class PersistentRunner : MonoBehaviour
	{
		private float _heartbeatTimer = 0f;

		private int _heartbeatCount = 0;

		private const float HEARTBEAT_INTERVAL = 30f;

		private void Awake()
		{
			((Object)((Component)this).gameObject).hideFlags = (HideFlags)61;
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"[PersistentRunner] Awake - hidden persistent runner active");
			}
		}

		private void Update()
		{
			CheckHotkeys();
			_heartbeatTimer += Time.deltaTime;
			if (_heartbeatTimer >= 30f)
			{
				_heartbeatTimer = 0f;
				_heartbeatCount++;
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)string.Format("[PersistentRunner Heartbeat #{0}] Authorized: {1}, Player: {2}", _heartbeatCount, Plugin.IsAuthorized, Plugin.CurrentPlayerName ?? "none"));
				}
			}
		}

		private void CheckHotkeys()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (Input.GetKeyDown(Plugin.StaticToggleKey))
				{
					Plugin.ToggleDebugWindow();
				}
				if (Input.GetKeyDown(Plugin.StaticOverlayToggleKey))
				{
					Plugin.ToggleDebugOverlay();
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogError((object)("[PersistentRunner] Hotkey error: " + ex.Message));
				}
			}
		}

		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.havendevtools";

		public const string PLUGIN_NAME = "Haven Dev Tools";

		public const string PLUGIN_VERSION = "1.0.4";
	}
}
namespace HavenDevTools.UI
{
	public class DebugOverlay : MonoBehaviour
	{
		private bool _isVisible;

		private GUIStyle _overlayStyle;

		private GUIStyle _labelStyle;

		private GUIStyle _valueStyle;

		private bool _stylesInitialized;

		private float _updateTimer;

		private const float UPDATE_INTERVAL = 0.5f;

		private string _playerName = "";

		private string _currentRace = "";

		private int _gold;

		private string _heldItemInfo = "";

		private string _position = "";

		private void Awake()
		{
			_isVisible = ModConfig.ShowOverlayOnStart?.Value ?? false;
		}

		public void Toggle()
		{
			_isVisible = !_isVisible;
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("[DebugOverlay] " + (_isVisible ? "Shown" : "Hidden")));
			}
		}

		public void Show()
		{
			_isVisible = true;
		}

		public void Hide()
		{
			_isVisible = false;
		}

		private void Update()
		{
			if (_isVisible && Plugin.IsAuthorized)
			{
				_updateTimer += Time.deltaTime;
				if (_updateTimer >= 0.5f)
				{
					_updateTimer = 0f;
					UpdateCachedData();
				}
			}
		}

		private void UpdateCachedData()
		{
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: 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_00db: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_playerName = Plugin.CurrentPlayerName ?? "Unknown";
				_currentRace = Plugin.GetRaceModifierTracker()?.GetCurrentRace() ?? "Unknown";
				_gold = Plugin.GetCurrencyTracker()?.GetGold() ?? 0;
				(int, string)? tuple = Plugin.GetItemInspector()?.GetHeldItem();
				_heldItemInfo = (tuple.HasValue ? $"{tuple.Value.Item2} ({tuple.Value.Item1})" : "None");
				if ((Object)(object)Player.Instance != (Object)null)
				{
					Vector3 position = ((Component)Player.Instance).transform.position;
					_position = $"({position.x:F1}, {position.y:F1})";
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[DebugOverlay] Update error: " + ex.Message));
				}
			}
		}

		private void OnGUI()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			if (_isVisible && Plugin.IsAuthorized)
			{
				InitializeStyles();
				OverlayPositionType overlayPosition = ModConfig.GetOverlayPosition();
				Rect overlayRect = GetOverlayRect(overlayPosition);
				GUI.Box(overlayRect, "", _overlayStyle);
				GUILayout.BeginArea(new Rect(((Rect)(ref overlayRect)).x + 8f, ((Rect)(ref overlayRect)).y + 8f, ((Rect)(ref overlayRect)).width - 16f, ((Rect)(ref overlayRect)).height - 16f));
				DrawOverlayContent();
				GUILayout.EndArea();
			}
		}

		private void InitializeStyles()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Expected O, but got Unknown
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			if (!_stylesInitialized)
			{
				Texture2D val = new Texture2D(1, 1);
				val.SetPixel(0, 0, new Color(0.05f, 0.05f, 0.1f, 0.85f));
				val.Apply();
				GUIStyle val2 = new GUIStyle(GUI.skin.box);
				val2.normal.background = val;
				_overlayStyle = val2;
				GUIStyle val3 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 11
				};
				val3.normal.textColor = new Color(0.7f, 0.7f, 0.8f);
				_labelStyle = val3;
				GUIStyle val4 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 11,
					fontStyle = (FontStyle)1
				};
				val4.normal.textColor = new Color(0.9f, 0.95f, 1f);
				_valueStyle = val4;
				_stylesInitialized = true;
			}
		}

		private Rect GetOverlayRect(OverlayPositionType position)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			float num = 220f;
			ConfigEntry<bool> showPerformance = ModConfig.ShowPerformance;
			float num2 = ((showPerformance == null || showPerformance.Value) ? 155 : 130);
			float num3 = 10f;
			if (1 == 0)
			{
			}
			Rect result = (Rect)(position switch
			{
				OverlayPositionType.TopLeft => new Rect(num3, num3, num, num2), 
				OverlayPositionType.TopRight => new Rect((float)Screen.width - num - num3, num3, num, num2), 
				OverlayPositionType.BottomLeft => new Rect(num3, (float)Screen.height - num2 - num3, num, num2), 
				OverlayPositionType.BottomRight => new Rect((float)Screen.width - num - num3, (float)Screen.height - num2 - num3, num, num2), 
				_ => new Rect((float)Screen.width - num - num3, num3, num, num2), 
			});
			if (1 == 0)
			{
			}
			return result;
		}

		private void DrawOverlayContent()
		{
			GUILayout.Label("Haven Dev Tools", _valueStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(3f);
			DrawRow("Player:", _playerName);
			DrawRow("Race:", _currentRace);
			DrawRow("Gold:", _gold.ToString("N0"));
			DrawRow("Position:", _position);
			DrawRow("Held:", _heldItemInfo);
			ConfigEntry<bool> showPerformance = ModConfig.ShowPerformance;
			if (showPerformance == null || showPerformance.Value)
			{
				float num = 1f / Mathf.Max(0.0001f, Time.deltaTime);
				long totalMemory = GC.GetTotalMemory(forceFullCollection: false);
				float num2 = (float)totalMemory / 1048576f;
				DrawRow("FPS:", num.ToString("F1"));
				DrawRow("Memory:", $"{num2:F1} MB");
			}
			GUILayout.FlexibleSpace();
			GUILayout.Label("F11: Window | F6: Toggle", _labelStyle, Array.Empty<GUILayoutOption>());
		}

		private void DrawRow(string label, string value)
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(label, _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(55f) });
			GUILayout.Label(value, _valueStyle, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
		}
	}
	public class DebugWindow : MonoBehaviour
	{
		private bool _isVisible;

		private Rect _windowRect;

		private Vector2 _scrollPosition;

		private GUIStyle _windowStyle;

		private GUIStyle _headerStyle;

		private GUIStyle _sectionHeaderStyle;

		private GUIStyle _buttonStyle;

		private GUIStyle _labelStyle;

		private GUIStyle _textFieldStyle;

		private GUIStyle _boxStyle;

		private bool _stylesInitialized;

		private int _selectedTab;

		private readonly string[] _tabNames = new string[3] { "Tools", "Azrael's Mods", "Extensions" };

		private int _toolsSubTab;

		private readonly string[] _toolsSubTabNames = new string[6] { "Items", "Currencies", "Console", "Log", "Perf", "Utility" };

		private string _itemSearchText = "";

		private string _lastItemSearchQuery = null;

		private string _itemIdInput = "";

		private string _spawnAmount = "1";

		private int _selectedItemId;

		private string _selectedItemName = "";

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

		private Vector2 _itemScrollPosition;

		private Vector2 _currencyScrollPosition;

		private int _selectedSectionIndex;

		private int _selectedBundleIndex;

		private Vector2 _bundleScrollPosition;

		private int _selectedRaceIndex;

		private Vector2 _raceScrollPosition;

		private static Dictionary<string, VersionChecker.VersionCheckResult> _versionResults = new Dictionary<string, VersionChecker.VersionCheckResult>();

		private static bool _isCheckingVersions;

		private Vector2 _versionScrollPosition;

		private static readonly (string guid, string name, string version)[] _knownMods = new(string, string, string)[8]
		{
			("com.azraelgodking.havendevtools", "Haven Dev Tools", "1.0.2"),
			("com.azraelgodking.senpaischest", "Senpai's Chest", "2.0.0"),
			("com.azraelgodking.squirrelsbirthdayreminder", "Birthday Reminder", "1.0.2"),
			("com.azraelgodking.havensbirthright", "Haven's Birthright", "1.0.2"),
			("com.azraelgodking.sunhavenmuseumutilitytracker", "S.M.U.T.", "2.0.1"),
			("com.azraelgodking.sunhaventodo", "Sunhaven Todo", "1.0.0"),
			("com.azraelgodking.thevault", "The Vault", "2.0.3"),
			("com.azraelgodking.havensalmanac", "Haven's Almanac", "1.0.0")
		};

		private const string PAUSE_ID = "HavenDevTools_Debug";

		private void Awake()
		{
			//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)
			_windowRect = new Rect(50f, 50f, 500f, 600f);
		}

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

		public void Show()
		{
			_isVisible = true;
			BlockInput();
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"[DebugWindow] Shown");
			}
		}

		public void Hide()
		{
			_isVisible = false;
			UnblockInput();
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"[DebugWindow] Hidden");
			}
		}

		private void BlockInput()
		{
			try
			{
				if ((Object)(object)Player.Instance != (Object)null)
				{
					Player.Instance.AddPauseObject("HavenDevTools_Debug");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[DebugWindow] Could not block input: " + ex.Message));
				}
			}
		}

		private void UnblockInput()
		{
			try
			{
				if ((Object)(object)Player.Instance != (Object)null)
				{
					Player.Instance.RemovePauseObject("HavenDevTools_Debug");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[DebugWindow] Could not unblock input: " + ex.Message));
				}
			}
		}

		private void Update()
		{
			if (_isVisible && Input.GetKeyDown((KeyCode)27))
			{
				Hide();
			}
		}

		private void OnGUI()
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			if (_isVisible && Plugin.IsAuthorized)
			{
				InitializeStyles();
				_windowRect = GUI.Window(((object)this).GetHashCode(), _windowRect, new WindowFunction(DrawWindow), "", _windowStyle);
			}
		}

		private void InitializeStyles()
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0031: 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)
			//IL_004b: Expected O, but got Unknown
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Expected O, but got Unknown
			//IL_00c4: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: 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_0104: 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)
			//IL_0117: Expected O, but got Unknown
			//IL_011d: Expected O, but got Unknown
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Expected O, but got Unknown
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Expected O, but got Unknown
			//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_020b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Expected O, but got Unknown
			//IL_021b: Expected O, but got Unknown
			//IL_0226: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Expected O, but got Unknown
			//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_0272: Unknown result type (might be due to invalid IL or missing references)
			//IL_0278: Unknown result type (might be due to invalid IL or missing references)
			//IL_0288: Expected O, but got Unknown
			//IL_0293: Unknown result type (might be due to invalid IL or missing references)
			//IL_0298: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Expected O, but got Unknown
			if (!_stylesInitialized)
			{
				Texture2D val = new Texture2D(1, 1);
				val.SetPixel(0, 0, new Color(0.08f, 0.08f, 0.12f, 0.98f));
				val.Apply();
				Texture2D val2 = new Texture2D(1, 1);
				val2.SetPixel(0, 0, new Color(0.2f, 0.4f, 0.6f, 0.9f));
				val2.Apply();
				Texture2D val3 = new Texture2D(1, 1);
				val3.SetPixel(0, 0, new Color(0.3f, 0.5f, 0.7f, 0.95f));
				val3.Apply();
				Texture2D val4 = new Texture2D(1, 1);
				val4.SetPixel(0, 0, new Color(0.12f, 0.12f, 0.18f, 0.9f));
				val4.Apply();
				GUIStyle val5 = new GUIStyle(GUI.skin.window);
				val5.normal.background = val;
				val5.normal.textColor = Color.white;
				val5.padding = new RectOffset(10, 10, 25, 10);
				_windowStyle = val5;
				GUIStyle val6 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 18,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)4
				};
				val6.normal.textColor = new Color(0.4f, 0.8f, 1f);
				_headerStyle = val6;
				GUIStyle val7 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 14,
					fontStyle = (FontStyle)1
				};
				val7.normal.textColor = new Color(0.8f, 0.9f, 1f);
				_sectionHeaderStyle = val7;
				GUIStyle val8 = new GUIStyle(GUI.skin.button)
				{
					fontSize = 12
				};
				val8.normal.background = val2;
				val8.normal.textColor = Color.white;
				val8.hover.background = val3;
				val8.hover.textColor = Color.white;
				val8.padding = new RectOffset(8, 8, 4, 4);
				_buttonStyle = val8;
				GUIStyle val9 = new GUIStyle(GUI.skin.label)
				{
					fontSize = 12
				};
				val9.normal.textColor = new Color(0.9f, 0.9f, 0.95f);
				_labelStyle = val9;
				GUIStyle val10 = new GUIStyle(GUI.skin.textField)
				{
					fontSize = 12
				};
				val10.normal.textColor = Color.white;
				_textFieldStyle = val10;
				GUIStyle val11 = new GUIStyle(GUI.skin.box);
				val11.normal.background = val4;
				_boxStyle = val11;
				_stylesInitialized = true;
			}
		}

		private void DrawWindow(int windowId)
		{
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label("Haven Dev Tools", _headerStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Player: " + Plugin.CurrentPlayerName, _labelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(5f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("TheVault: " + (Plugin.HasTheVault ? "Yes" : "No"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) });
			GUILayout.Label("SMUT: " + (Plugin.HasSMUT ? "Yes" : "No"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
			GUILayout.Label("Birthright: " + (Plugin.HasHavensBirthright ? "Yes" : "No"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) });
			GUILayout.Label("Senpai: " + (Plugin.HasSenpaisChest ? "Yes" : "No"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
			GUILayout.Label("Todo: " + (Plugin.HasSunhavenTodo ? "Yes" : "No"), _labelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.EndHorizontal();
			GUILayout.Space(10f);
			_selectedTab = GUILayout.Toolbar(_selectedTab, _tabNames, _buttonStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			_scrollPosition = GUILayout.BeginScrollView(_scrollPosition, Array.Empty<GUILayoutOption>());
			switch (_selectedTab)
			{
			case 0:
				DrawToolsTab();
				break;
			case 1:
				AzraelsModsPanel.Draw(_boxStyle, _buttonStyle, _labelStyle, _sectionHeaderStyle);
				break;
			case 2:
				DrawExtensionsTab();
				break;
			}
			GUILayout.EndScrollView();
			GUILayout.Space(10f);
			if (GUILayout.Button("Close (Esc)", _buttonStyle, Array.Empty<GUILayoutOption>()))
			{
				Hide();
			}
			GUI.DragWindow(new Rect(0f, 0f, 500f, 30f));
		}

		private void DrawExtensionsTab()
		{
			IReadOnlyList<IDevToolsPanel> panels = DevToolsRegistry.Panels;
			if (panels.Count == 0)
			{
				GUILayout.BeginVertical(_boxStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Label("Extensions", _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Space(5f);
				GUILayout.Label("No extension panels registered. Mods can implement IDevToolsPanel and call DevToolsRegistry.Register() to add panels here.", _labelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.EndVertical();
				return;
			}
			foreach (IDevToolsPanel item in panels)
			{
				GUILayout.BeginVertical(_boxStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Label(item.DisplayName, _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Space(5f);
				try
				{
					item.Draw(_boxStyle, _buttonStyle, _labelStyle);
				}
				catch (Exception ex)
				{
					GUILayout.Label("Error: " + ex.Message, _labelStyle, Array.Empty<GUILayoutOption>());
				}
				GUILayout.EndVertical();
				GUILayout.Space(8f);
			}
		}

		private void DrawToolsTab()
		{
			_toolsSubTab = GUILayout.Toolbar(_toolsSubTab, _toolsSubTabNames, _buttonStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(8f);
			switch (_toolsSubTab)
			{
			case 0:
				DrawItemsTab();
				break;
			case 1:
				DrawCurrenciesTab();
				break;
			case 2:
				DrawConsoleTab();
				break;
			case 3:
				DrawLogViewerTab();
				break;
			case 4:
				DrawPerformanceTab();
				break;
			case 5:
				DrawUtilityTab();
				break;
			}
		}

		private void DrawConsoleTab()
		{
			GUILayout.BeginVertical(_boxStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Command Console", _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(5f);
			GUILayout.Label("Type commands and press Enter. Supported: spawn, tp, time.set, reload.config", _labelStyle, Array.Empty<GUILayoutOption>());
			CommandConsole commandConsole = Plugin.GetCommandConsole();
			if (commandConsole != null)
			{
				commandConsole.Draw(_boxStyle, _buttonStyle, _labelStyle, _textFieldStyle);
			}
			else
			{
				GUILayout.Label("(Console service initializing...)", _labelStyle, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndVertical();
		}

		private void DrawLogViewerTab()
		{
			GUILayout.BeginVertical(_boxStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Log Viewer", _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(5f);
			LogViewerPanel logViewer = Plugin.GetLogViewer();
			if (logViewer != null)
			{
				logViewer.Draw(_boxStyle, _buttonStyle, _labelStyle);
			}
			else
			{
				GUILayout.Label("(Log viewer initializing...)", _labelStyle, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndVertical();
		}

		private void DrawPerformanceTab()
		{
			GUILayout.BeginVertical(_boxStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Performance", _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(5f);
			float num = 1f / Mathf.Max(0.0001f, Time.deltaTime);
			long totalMemory = GC.GetTotalMemory(forceFullCollection: false);
			float num2 = (float)totalMemory / 1048576f;
			GUILayout.Label($"FPS: {num:F1}", _labelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label($"Memory: {num2:F1} MB", _labelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label("(Also shown in overlay when ShowPerformance is enabled)", _labelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.EndVertical();
		}

		private void DrawItemsTab()
		{
			//IL_0204: 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_021e: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(_boxStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Item Inspector", _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(5f);
			(int, string)? tuple = Plugin.GetItemInspector()?.GetHeldItem();
			if (tuple.HasValue)
			{
				GUILayout.Label($"Held: {tuple.Value.Item2} ({tuple.Value.Item1})", _labelStyle, Array.Empty<GUILayoutOption>());
			}
			else
			{
				GUILayout.Label("Held: None", _labelStyle, Array.Empty<GUILayoutOption>());
			}
			GUILayout.Space(10f);
			GUILayout.Label("Search:", _labelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			_itemSearchText = GUILayout.TextField(_itemSearchText, _textFieldStyle, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Clear", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) }))
			{
				_itemSearchText = "";
				_lastItemSearchQuery = "";
				_searchResults.Clear();
			}
			GUILayout.EndHorizontal();
			if (_itemSearchText != _lastItemSearchQuery)
			{
				_lastItemSearchQuery = _itemSearchText;
				_searchResults = ItemSearch.SearchItems(_itemSearchText);
			}
			if (_selectedItemId > 0)
			{
				GUILayout.Space(2f);
				GUILayout.Label("Selected: " + ItemSearch.FormatDisplay(_selectedItemName, _selectedItemId), _labelStyle, Array.Empty<GUILayoutOption>());
			}
			if (_searchResults.Count > 0)
			{
				GUILayout.Space(4f);
				float num = Mathf.Min(180, 24 + _searchResults.Count * 22);
				_itemScrollPosition = GUILayout.BeginScrollView(_itemScrollPosition, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(num) });
				foreach (KeyValuePair<int, string> searchResult in _searchResults)
				{
					string text = ItemSearch.FormatDisplay(searchResult.Value, searchResult.Key);
					bool flag = searchResult.Key == _selectedItemId;
					if (GUILayout.Button(text, flag ? _buttonStyle : _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(22f) }))
					{
						_selectedItemId = searchResult.Key;
						_selectedItemName = searchResult.Value;
						_itemIdInput = searchResult.Key.ToString();
					}
				}
				GUILayout.EndScrollView();
			}
			else if (_itemSearchText.Length >= 2)
			{
				GUILayout.Space(2f);
				GUILayout.Label("No items found.", _labelStyle, Array.Empty<GUILayoutOption>());
			}
			GUILayout.Space(10f);
			GUILayout.Label("Spawn:", _labelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("ID:", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(22f) });
			_itemIdInput = GUILayout.TextField(_itemIdInput, _textFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) });
			GUILayout.Label("Qty:", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(28f) });
			_spawnAmount = GUILayout.TextField(_spawnAmount, _textFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
			if (GUILayout.Button("1", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(22f) }))
			{
				_spawnAmount = "1";
			}
			if (GUILayout.Button("10", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(28f) }))
			{
				_spawnAmount = "10";
			}
			if (GUILayout.Button("99", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(28f) }))
			{
				_spawnAmount = "99";
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Spawn to Inventory", _buttonStyle, Array.Empty<GUILayoutOption>()) && int.TryParse(_itemIdInput, out var result) && int.TryParse(_spawnAmount, out var result2) && result2 > 0)
			{
				Plugin.GetItemInspector()?.SpawnItem(result, result2);
			}
			if (_selectedItemId > 0 && GUILayout.Button("Spawn 1", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }))
			{
				Plugin.GetItemInspector()?.SpawnItem(_selectedItemId);
			}
			GUILayout.EndHorizontal();
			GUILayout.EndVertical();
		}

		private void DrawCurrenciesTab()
		{
			//IL_00ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: 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)
			GUILayout.BeginVertical(_boxStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Currency Tracker", _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(5f);
			CurrencyTracker currencyTracker = Plugin.GetCurrencyTracker();
			if (currencyTracker == null)
			{
				GUILayout.Label("Currency tracker not available", _labelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.EndVertical();
				return;
			}
			CurrencySummary summary = currencyTracker.GetSummary();
			GUILayout.Label($"Gold: {summary.Gold:N0}", _labelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label($"Orbs: {summary.Orbs:N0}", _labelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label($"Tickets: {summary.Tickets:N0}", _labelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			GUILayout.Label("Inventory Currencies:", _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
			_currencyScrollPosition = GUILayout.BeginScrollView(_currencyScrollPosition, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(120f) });
			if (summary.InventoryCurrencies.Count == 0)
			{
				GUILayout.Label("  (none)", _labelStyle, Array.Empty<GUILayoutOption>());
			}
			else
			{
				foreach (KeyValuePair<string, int> inventoryCurrency in summary.InventoryCurrencies)
				{
					GUILayout.Label($"  {inventoryCurrency.Key}: {inventoryCurrency.Value}", _labelStyle, Array.Empty<GUILayoutOption>());
				}
			}
			GUILayout.EndScrollView();
			if (Plugin.HasTheVault)
			{
				GUILayout.Space(10f);
				GUILayout.Label("Vault Currencies:", _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
				if (summary.VaultCurrencies.Count == 0)
				{
					GUILayout.Label("  (vault empty)", _labelStyle, Array.Empty<GUILayoutOption>());
				}
				else
				{
					foreach (KeyValuePair<string, int> vaultCurrency in summary.VaultCurrencies)
					{
						GUILayout.Label($"  {vaultCurrency.Key}: {vaultCurrency.Value}", _labelStyle, Array.Empty<GUILayoutOption>());
					}
				}
			}
			else
			{
				GUILayout.Space(5f);
				GUILayout.Label("(The Vault not installed)", _labelStyle, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndVertical();
		}

		private void DrawBundlesTab()
		{
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_0329: Unknown result type (might be due to invalid IL or missing references)
			//IL_032e: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(_boxStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Museum Bundle Inspector", _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(5f);
			if (!Plugin.HasSMUT)
			{
				GUILayout.Label("S.M.U.T. not installed", _labelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.EndVertical();
				return;
			}
			BundleInspector bundleInspector = Plugin.GetBundleInspector();
			if (bundleInspector == null)
			{
				GUILayout.Label("Bundle inspector not available", _labelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.EndVertical();
				return;
			}
			DonationStats donationStats = bundleInspector.GetDonationStats();
			if (donationStats.IsLoaded)
			{
				GUILayout.Label("Character: " + donationStats.CharacterName, _labelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Label($"Progress: {donationStats.TotalDonated}/{donationStats.TotalItems} ({donationStats.CompletionPercent:F1}%)", _labelStyle, Array.Empty<GUILayoutOption>());
			}
			else
			{
				GUILayout.Label("Donation data not loaded", _labelStyle, Array.Empty<GUILayoutOption>());
			}
			GUILayout.Space(10f);
			List<MuseumSectionInfo> allSections = bundleInspector.GetAllSections();
			if (allSections.Count == 0)
			{
				GUILayout.Label("No museum data available", _labelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.EndVertical();
				return;
			}
			string[] array = new string[allSections.Count];
			for (int i = 0; i < allSections.Count; i++)
			{
				array[i] = allSections[i].Name;
			}
			GUILayout.Label("Section:", _labelStyle, Array.Empty<GUILayoutOption>());
			_selectedSectionIndex = GUILayout.SelectionGrid(_selectedSectionIndex, array, 3, _buttonStyle, Array.Empty<GUILayoutOption>());
			if (_selectedSectionIndex >= allSections.Count)
			{
				_selectedSectionIndex = 0;
			}
			MuseumSectionInfo museumSectionInfo = allSections[_selectedSectionIndex];
			GUILayout.Space(5f);
			if (museumSectionInfo.Bundles.Count > 0)
			{
				string[] array2 = new string[museumSectionInfo.Bundles.Count];
				for (int j = 0; j < museumSectionInfo.Bundles.Count; j++)
				{
					array2[j] = museumSectionInfo.Bundles[j].Name;
				}
				if (_selectedBundleIndex >= museumSectionInfo.Bundles.Count)
				{
					_selectedBundleIndex = 0;
				}
				GUILayout.Label("Bundle:", _labelStyle, Array.Empty<GUILayoutOption>());
				_selectedBundleIndex = GUILayout.SelectionGrid(_selectedBundleIndex, array2, 2, _buttonStyle, Array.Empty<GUILayoutOption>());
				MuseumBundleInfo museumBundleInfo = museumSectionInfo.Bundles[_selectedBundleIndex];
				GUILayout.Space(5f);
				GUILayout.Label("Items in " + museumBundleInfo.Name + ":", _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
				_bundleScrollPosition = GUILayout.BeginScrollView(_bundleScrollPosition, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(150f) });
				foreach (MuseumItemInfo item in museumBundleInfo.Items)
				{
					string arg = (bundleInspector.HasDonated(item.Id) ? "[X]" : "[ ]");
					string text = ((item.Quantity > 1) ? $" x{item.Quantity}" : "");
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					GUILayout.Label($"{arg} {item.Name} (ID: {item.GameItemId})", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(320f) });
					if (GUILayout.Button("Spawn" + text, _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(90f) }))
					{
						Plugin.GetItemInspector()?.SpawnItem(item.GameItemId, item.Quantity);
					}
					GUILayout.EndHorizontal();
				}
				GUILayout.EndScrollView();
			}
			GUILayout.EndVertical();
		}

		private void DrawRaceBonusesTab()
		{
			//IL_022a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(_boxStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Race Modifier Tracker", _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(5f);
			RaceModifierTracker raceModifierTracker = Plugin.GetRaceModifierTracker();
			if (raceModifierTracker == null)
			{
				GUILayout.Label("Race tracker not available", _labelStyle, Array.Empty<GUILayoutOption>());
				GUILayout.EndVertical();
				return;
			}
			string currentRace = raceModifierTracker.GetCurrentRace();
			GUILayout.Label("Current Race: " + currentRace, _labelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			if (Plugin.HasHavensBirthright)
			{
				List<RaceBonusInfo> activeRaceBonuses = raceModifierTracker.GetActiveRaceBonuses();
				GUILayout.Label("Active Bonuses:", _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
				if (activeRaceBonuses.Count == 0)
				{
					GUILayout.Label("  (no bonuses active)", _labelStyle, Array.Empty<GUILayoutOption>());
				}
				else
				{
					foreach (RaceBonusInfo item in activeRaceBonuses)
					{
						GUILayout.Label("  " + item.Type + ": " + item.GetFormattedValue(), _labelStyle, Array.Empty<GUILayoutOption>());
						GUILayout.Label("    " + item.Description, _labelStyle, Array.Empty<GUILayoutOption>());
					}
				}
			}
			else
			{
				GUILayout.Label("Haven's Birthright not installed", _labelStyle, Array.Empty<GUILayoutOption>());
			}
			GUILayout.Space(10f);
			GUILayout.Label("Browse Race Bonuses:", _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
			List<string> allRaces = raceModifierTracker.GetAllRaces();
			if (allRaces.Count > 0)
			{
				string[] array = allRaces.ToArray();
				if (_selectedRaceIndex >= allRaces.Count)
				{
					_selectedRaceIndex = 0;
				}
				_selectedRaceIndex = GUILayout.SelectionGrid(_selectedRaceIndex, array, 4, _buttonStyle, Array.Empty<GUILayoutOption>());
				GUILayout.Space(5f);
				List<RaceBonusInfo> bonusesForRace = raceModifierTracker.GetBonusesForRace(allRaces[_selectedRaceIndex]);
				_raceScrollPosition = GUILayout.BeginScrollView(_raceScrollPosition, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(150f) });
				if (bonusesForRace.Count == 0)
				{
					GUILayout.Label("  (no bonuses defined)", _labelStyle, Array.Empty<GUILayoutOption>());
				}
				else
				{
					foreach (RaceBonusInfo item2 in bonusesForRace)
					{
						GUILayout.Label("  " + item2.Type + ": " + item2.GetFormattedValue(), _labelStyle, Array.Empty<GUILayoutOption>());
						GUILayout.Label("    " + item2.Description, _labelStyle, Array.Empty<GUILayoutOption>());
					}
				}
				GUILayout.EndScrollView();
			}
			GUILayout.EndVertical();
		}

		private void DrawUtilityTab()
		{
			GUILayout.BeginVertical(_boxStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Utility", _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(5f);
			DrawVersionCheckerSection();
			GUILayout.Space(10f);
			GUILayout.Label("Config:", _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Reload HavenDevTools Config", _buttonStyle, Array.Empty<GUILayoutOption>()))
			{
				ConfigReloader.ReloadHavenDevToolsConfig();
			}
			GUILayout.Space(10f);
			GUILayout.Label("Logging:", _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Log All Currency IDs", _buttonStyle, Array.Empty<GUILayoutOption>()))
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)"=== Currency Item IDs ===");
				}
				foreach (KeyValuePair<string, int> currencyItemId in CurrencyTracker.CurrencyItemIds)
				{
					ManualLogSource log2 = Plugin.Log;
					if (log2 != null)
					{
						log2.LogInfo((object)$"  {currencyItemId.Key}: {currencyItemId.Value}");
					}
				}
			}
			if (GUILayout.Button("Log Player Stats", _buttonStyle, Array.Empty<GUILayoutOption>()))
			{
				LogPlayerStats();
			}
			GUILayout.Space(10f);
			GUILayout.Label("Authorization Hash Generator:", _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Label("Use this to generate hashes for new authorized Steam IDs", _labelStyle, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Log Current Steam ID Hash", _buttonStyle, Array.Empty<GUILayoutOption>()))
			{
				try
				{
					string text = typeof(Plugin).GetMethod("TryGetSteamId", BindingFlags.Static | BindingFlags.NonPublic)?.Invoke(null, null) as string;
					if (!string.IsNullOrEmpty(text))
					{
						string text2 = Plugin.GenerateHash(text);
						ManualLogSource log3 = Plugin.Log;
						if (log3 != null)
						{
							log3.LogInfo((object)("Steam ID: " + text));
						}
						ManualLogSource log4 = Plugin.Log;
						if (log4 != null)
						{
							log4.LogInfo((object)("Steam ID Hash: " + text2));
						}
					}
					else
					{
						ManualLogSource log5 = Plugin.Log;
						if (log5 != null)
						{
							log5.LogWarning((object)"Could not retrieve Steam ID");
						}
					}
				}
				catch (Exception ex)
				{
					ManualLogSource log6 = Plugin.Log;
					if (log6 != null)
					{
						log6.LogError((object)("Error generating hash: " + ex.Message));
					}
				}
			}
			GUILayout.EndVertical();
		}

		private void DrawVersionCheckerSection()
		{
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0165: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			//IL_018c: Expected O, but got Unknown
			//IL_0213: Unknown result type (might be due to invalid IL or missing references)
			//IL_0218: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Expected O, but got Unknown
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Expected O, but got Unknown
			GUILayout.Label("Version Checker:", _sectionHeaderStyle, Array.Empty<GUILayoutOption>());
			GUILayout.Space(3f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUI.enabled = !_isCheckingVersions;
			if (GUILayout.Button(_isCheckingVersions ? "Checking..." : "Check All Mod Versions", _buttonStyle, Array.Empty<GUILayoutOption>()))
			{
				CheckAllModVersions();
			}
			GUI.enabled = true;
			if (GUILayout.Button("Test Notification", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(120f) }))
			{
				TestUpdateNotification();
			}
			GUILayout.EndHorizontal();
			GUILayout.Space(5f);
			_versionScrollPosition = GUILayout.BeginScrollView(_versionScrollPosition, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(140f) });
			(string, string, string)[] knownMods = _knownMods;
			for (int i = 0; i < knownMods.Length; i++)
			{
				(string, string, string) tuple = knownMods[i];
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				GUILayout.Label(tuple.Item2 + " v" + tuple.Item3, _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(200f) });
				if (_versionResults.TryGetValue(tuple.Item1, out var value))
				{
					if (!value.Success)
					{
						GUIStyle val = new GUIStyle(_labelStyle);
						val.normal.textColor = new Color(1f, 0.5f, 0.5f);
						GUIStyle val2 = val;
						GUILayout.Label("Error: " + value.ErrorMessage, val2, Array.Empty<GUILayoutOption>());
					}
					else if (value.UpdateAvailable)
					{
						GUIStyle val3 = new GUIStyle(_labelStyle);
						val3.normal.textColor = new Color(1f, 0.9f, 0.3f);
						GUIStyle val4 = val3;
						GUILayout.Label("Update: v" + value.LatestVersion, val4, Array.Empty<GUILayoutOption>());
					}
					else
					{
						GUIStyle val5 = new GUIStyle(_labelStyle);
						val5.normal.textColor = new Color(0.5f, 1f, 0.5f);
						GUIStyle val6 = val5;
						GUILayout.Label("Up to date", val6, Array.Empty<GUILayoutOption>());
					}
				}
				else
				{
					GUILayout.Label("Not checked", _labelStyle, Array.Empty<GUILayoutOption>());
				}
				GUILayout.EndHorizontal();
			}
			GUILayout.EndScrollView();
		}

		private void CheckAllModVersions()
		{
			_isCheckingVersions = true;
			_versionResults.Clear();
			int pendingChecks = _knownMods.Length;
			(string, string, string)[] knownMods = _knownMods;
			for (int i = 0; i < knownMods.Length; i++)
			{
				(string guid, string name, string version) mod = knownMods[i];
				VersionChecker.CheckForUpdate(mod.guid, mod.version, Plugin.Log, delegate(VersionChecker.VersionCheckResult result)
				{
					_versionResults[mod.guid] = result;
					int num = pendingChecks;
					pendingChecks = num - 1;
					if (pendingChecks <= 0)
					{
						_isCheckingVersions = false;
					}
					if (result.Success)
					{
						if (result.UpdateAvailable)
						{
							ManualLogSource log = Plugin.Log;
							if (log != null)
							{
								log.LogInfo((object)("[VersionChecker] " + mod.name + ": Update available v" + result.LatestVersion));
							}
						}
						else
						{
							ManualLogSource log2 = Plugin.Log;
							if (log2 != null)
							{
								log2.LogInfo((object)("[VersionChecker] " + mod.name + ": Up to date (v" + mod.version + ")"));
							}
						}
					}
					else
					{
						ManualLogSource log3 = Plugin.Log;
						if (log3 != null)
						{
							log3.LogWarning((object)("[VersionChecker] " + mod.name + ": " + result.ErrorMessage));
						}
					}
				});
			}
		}

		private void TestUpdateNotification()
		{
			VersionChecker.VersionCheckResult result = new VersionChecker.VersionCheckResult
			{
				Success = true,
				UpdateAvailable = true,
				CurrentVersion = "1.0.0",
				LatestVersion = "9.9.9",
				ModName = "Test Mod (HavenDevTools)",
				NexusUrl = "https://www.nexusmods.com/sunhaven"
			};
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"[VersionChecker] Testing notification system...");
			}
			result.NotifyUpdateAvailable(Plugin.Log);
		}

		private void LogPlayerStats()
		{
			try
			{
				if ((Object)(object)Player.Instance == (Object)null)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogInfo((object)"Player not available");
					}
					return;
				}
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)"=== Player Stats ===");
				}
				Type type = ((object)Player.Instance).GetType();
				PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
				PropertyInfo[] array = properties;
				foreach (PropertyInfo propertyInfo in array)
				{
					try
					{
						if (!propertyInfo.CanRead || propertyInfo.GetIndexParameters().Length != 0)
						{
							continue;
						}
						object value = propertyInfo.GetValue(Player.Instance);
						if (value != null && (value is int || value is float || value is string || value is bool))
						{
							ManualLogSource log3 = Plugin.Log;
							if (log3 != null)
							{
								log3.LogInfo((object)$"  {propertyInfo.Name}: {value}");
							}
						}
					}
					catch (Exception ex)
					{
						ManualLogSource log4 = Plugin.Log;
						if (log4 != null)
						{
							log4.LogDebug((object)("[DebugWindow] Player stats property iteration: " + ex.Message));
						}
					}
				}
			}
			catch (Exception ex2)
			{
				ManualLogSource log5 = Plugin.Log;
				if (log5 != null)
				{
					log5.LogError((object)("Error logging player stats: " + ex2.Message));
				}
			}
		}
	}
	public class LogViewerPanel
	{
		private class LogCaptureListener : ILogListener, IDisposable
		{
			public void LogEvent(object sender, LogEventArgs eventArgs)
			{
				OnLog(eventArgs);
			}

			public void Dispose()
			{
			}
		}

		private class LogEntry
		{
			public int Level;

			public string Message;

			public string Source;

			public DateTime Timestamp;
		}

		private static readonly List<LogEntry> _entries = new List<LogEntry>();

		private static readonly object _lock = new object();

		private Vector2 _scrollPosition;

		private int _levelFilterIndex = 1;

		private static readonly string[] _levelNames = new string[4] { "Debug", "Info", "Warning", "Error" };

		private static bool _listenerAttached;

		private static readonly LogCaptureListener _captureListener = new LogCaptureListener();

		public LogViewerPanel()
		{
			if (!_listenerAttached)
			{
				Logger.Listeners.Add((ILogListener)(object)_captureListener);
				_listenerAttached = true;
			}
		}

		private static void OnLog(LogEventArgs e)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Invalid comparison between Unknown and I4
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Invalid comparison between Unknown and I4
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Invalid comparison between Unknown and I4
			LogLevel level = e.Level;
			if (1 == 0)
			{
			}
			int num;
			if ((int)level <= 4)
			{
				if ((int)level != 2)
				{
					if ((int)level != 4)
					{
						goto IL_003a;
					}
					num = 2;
				}
				else
				{
					num = 3;
				}
			}
			else if ((int)level != 16)
			{
				if ((int)level != 32)
				{
					goto IL_003a;
				}
				num = 0;
			}
			else
			{
				num = 1;
			}
			goto IL_003e;
			IL_003e:
			if (1 == 0)
			{
			}
			int level2 = num;
			lock (_lock)
			{
				_entries.Add(new LogEntry
				{
					Level = level2,
					Message = (e.Data?.ToString() ?? ""),
					Source = e.Source.SourceName,
					Timestamp = DateTime.Now
				});
				int num2 = ModConfig.MaxLogEntries?.Value ?? 500;
				while (_entries.Count > num2)
				{
					_entries.RemoveAt(0);
				}
				return;
			}
			IL_003a:
			num = 1;
			goto IL_003e;
		}

		public void Draw(GUIStyle boxStyle, GUIStyle buttonStyle, GUIStyle labelStyle)
		{
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0152: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: 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_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Expected O, but got Unknown
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("Level:", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(40f) });
			_levelFilterIndex = GUILayout.Toolbar(_levelFilterIndex, _levelNames, buttonStyle, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Export", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
			{
				ExportToFile();
			}
			GUILayout.EndHorizontal();
			GUILayout.Space(5f);
			List<LogEntry> list;
			lock (_lock)
			{
				list = new List<LogEntry>(_entries);
			}
			_scrollPosition = GUILayout.BeginScrollView(_scrollPosition, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(200f) });
			int levelFilterIndex = _levelFilterIndex;
			foreach (LogEntry item in list)
			{
				if (item.Level >= levelFilterIndex)
				{
					int level = item.Level;
					if (1 == 0)
					{
					}
					Color val = (Color)(level switch
					{
						0 => new Color(0.6f, 0.6f, 0.6f), 
						1 => new Color(0.9f, 0.9f, 0.9f), 
						2 => new Color(1f, 0.85f, 0.3f), 
						3 => new Color(1f, 0.4f, 0.4f), 
						_ => Color.white, 
					});
					if (1 == 0)
					{
					}
					Color textColor = val;
					GUIStyle val2 = new GUIStyle(labelStyle);
					val2.normal.textColor = textColor;
					GUIStyle val3 = val2;
					string text = $"[{item.Timestamp:HH:mm:ss}] [{_levelNames[item.Level]}] [{item.Source}] {item.Message}";
					GUILayout.Label(text, val3, Array.Empty<GUILayoutOption>());
				}
			}
			GUILayout.EndScrollView();
		}

		private static void ExportToFile()
		{
			try
			{
				string text = Path.Combine(Paths.BepInExRootPath, "LogExport.txt");
				List<LogEntry> list;
				lock (_lock)
				{
					list = new List<LogEntry>(_entries);
				}
				List<string> list2 = new List<string>();
				foreach (LogEntry item in list)
				{
					list2.Add($"[{item.Timestamp:yyyy-MM-dd HH:mm:ss}] [{_levelNames[item.Level]}] [{item.Source}] {item.Message}");
				}
				File.WriteAllLines(text, list2);
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)$"[LogViewer] Exported {list2.Count} lines to {text}");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogError((object)("[LogViewer] Export failed: " + ex.Message));
				}
			}
		}
	}
}
namespace HavenDevTools.Services
{
	public class BundleInspector
	{
		public BundleInspector()
		{
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"[BundleInspector] Initialized");
			}
		}

		public List<MuseumSectionInfo> GetAllSections()
		{
			List<MuseumSectionInfo> list = new List<MuseumSectionInfo>();
			if (!Plugin.HasSMUT)
			{
				return list;
			}
			try
			{
				Assembly sMUTAssembly = GetSMUTAssembly();
				if (sMUTAssembly == null)
				{
					return list;
				}
				Type type = sMUTAssembly.GetType("SunHavenMuseumUtilityTracker.Data.MuseumContent");
				if (type == null)
				{
					return list;
				}
				MethodInfo method = type.GetMethod("GetAllSections", BindingFlags.Static | BindingFlags.Public);
				if (method == null)
				{
					return list;
				}
				if (!(method.Invoke(null, null) is IList list2))
				{
					return list;
				}
				foreach (object item2 in list2)
				{
					MuseumSectionInfo museumSectionInfo = new MuseumSectionInfo
					{
						Name = (item2.GetType().GetProperty("Name")?.GetValue(item2)?.ToString() ?? "Unknown"),
						Bundles = new List<MuseumBundleInfo>()
					};
					PropertyInfo property = item2.GetType().GetProperty("Bundles");
					if (property != null && property.GetValue(item2) is IList list3)
					{
						foreach (object item3 in list3)
						{
							MuseumBundleInfo museumBundleInfo = new MuseumBundleInfo
							{
								Name = (item3.GetType().GetProperty("Name")?.GetValue(item3)?.ToString() ?? "Unknown"),
								Items = new List<MuseumItemInfo>()
							};
							PropertyInfo property2 = item3.GetType().GetProperty("Items");
							if (property2 != null && property2.GetValue(item3) is IList list4)
							{
								foreach (object item4 in list4)
								{
									string name = item4.GetType().GetProperty("Name")?.GetValue(item4)?.ToString() ?? "Unknown";
									MuseumItemInfo item = new MuseumItemInfo
									{
										Id = (item4.GetType().GetProperty("Id")?.GetValue(item4)?.ToString() ?? ""),
										Name = name,
										GameItemId = Convert.ToInt32(item4.GetType().GetProperty("GameItemId")?.GetValue(item4) ?? ((object)0)),
										Quantity = MuseumItemInfo.ParseQuantityFromName(name)
									};
									museumBundleInfo.Items.Add(item);
								}
							}
							museumSectionInfo.Bundles.Add(museumBundleInfo);
						}
					}
					list.Add(museumSectionInfo);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[BundleInspector] Error getting sections: " + ex.Message));
				}
			}
			return list;
		}

		public DonationStats GetDonationStats()
		{
			DonationStats donationStats = new DonationStats();
			if (!Plugin.HasSMUT)
			{
				return donationStats;
			}
			try
			{
				Assembly sMUTAssembly = GetSMUTAssembly();
				if (sMUTAssembly == null)
				{
					return donationStats;
				}
				Type type = sMUTAssembly.GetType("SunHavenMuseumUtilityTracker.Plugin");
				if (type == null)
				{
					return donationStats;
				}
				MethodInfo method = type.GetMethod("GetDonationManager", BindingFlags.Static | BindingFlags.Public);
				if (method == null)
				{
					return donationStats;
				}
				object obj = method.Invoke(null, null);
				if (obj == null)
				{
					return donationStats;
				}
				PropertyInfo property = obj.GetType().GetProperty("IsLoaded");
				if (property != null && !(bool)property.GetValue(obj))
				{
					return donationStats;
				}
				MethodInfo method2 = obj.GetType().GetMethod("GetOverallStats");
				if (method2 != null)
				{
					object obj2 = method2.Invoke(obj, null);
					if (obj2 != null)
					{
						FieldInfo fieldInfo = obj2.GetType().GetField("donated") ?? obj2.GetType().GetField("Item1");
						FieldInfo fieldInfo2 = obj2.GetType().GetField("total") ?? obj2.GetType().GetField("Item2");
						if (fieldInfo != null)
						{
							donationStats.TotalDonated = Convert.ToInt32(fieldInfo.GetValue(obj2));
						}
						if (fieldInfo2 != null)
						{
							donationStats.TotalItems = Convert.ToInt32(fieldInfo2.GetValue(obj2));
						}
					}
				}
				MethodInfo method3 = obj.GetType().GetMethod("GetOverallCompletionPercent");
				if (method3 != null)
				{
					donationStats.CompletionPercent = (float)method3.Invoke(obj, null);
				}
				PropertyInfo property2 = obj.GetType().GetProperty("CurrentCharacter");
				if (property2 != null)
				{
					donationStats.CharacterName = property2.GetValue(obj)?.ToString() ?? "Unknown";
				}
				donationStats.IsLoaded = true;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[BundleInspector] Error getting donation stats: " + ex.Message));
				}
			}
			return donationStats;
		}

		public bool HasDonated(string itemId)
		{
			if (!Plugin.HasSMUT)
			{
				return false;
			}
			try
			{
				Assembly sMUTAssembly = GetSMUTAssembly();
				if (sMUTAssembly == null)
				{
					return false;
				}
				object obj = (sMUTAssembly.GetType("SunHavenMuseumUtilityTracker.Plugin")?.GetMethod("GetDonationManager", BindingFlags.Static | BindingFlags.Public))?.Invoke(null, null);
				if (obj == null)
				{
					return false;
				}
				MethodInfo method = obj.GetType().GetMethod("HasDonated", new Type[1] { typeof(string) });
				if (method != null)
				{
					return (bool)method.Invoke(obj, new object[1] { itemId });
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[BundleInspector] Error checking donation: " + ex.Message));
				}
			}
			return false;
		}

		private Assembly GetSMUTAssembly()
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				if (assembly.GetName().Name == "SunHavenMuseumUtilityTracker")
				{
					return assembly;
				}
			}
			return null;
		}
	}
	public class MuseumSectionInfo
	{
		public string Name { get; set; }

		public List<MuseumBundleInfo> Bundles { get; set; }
	}
	public class MuseumBundleInfo
	{
		public string Name { get; set; }

		public List<MuseumItemInfo> Items { get; set; }
	}
	public class MuseumItemInfo
	{
		public string Id { get; set; }

		public string Name { get; set; }

		public int GameItemId { get; set; }

		public int Quantity { get; set; } = 1;


		public static int ParseQuantityFromName(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return 1;
			}
			Match match = Regex.Match(name, "\\(x([\\d,]+)\\)");
			if (match.Success)
			{
				string s = match.Groups[1].Value.Replace(",", "");
				if (int.TryParse(s, out var result))
				{
					return result;
				}
			}
			return 1;
		}
	}
	public class DonationStats
	{
		public bool IsLoaded { get; set; }

		public string CharacterName { get; set; }

		public int TotalDonated { get; set; }

		public int TotalItems { get; set; }

		public float CompletionPercent { get; set; }
	}
	public class CommandConsole
	{
		private string _input = "";

		private readonly List<string> _output = new List<string>();

		private readonly List<string> _history = new List<string>();

		private int _historyIndex = -1;

		private Vector2 _outputScroll;

		private const int MaxOutputLines = 100;

		public void Draw(GUIStyle boxStyle, GUIStyle buttonStyle, GUIStyle labelStyle, GUIStyle textFieldStyle)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.Label("Output:", labelStyle, Array.Empty<GUILayoutOption>());
			float num = Mathf.Min(120, 20 + _output.Count * 18);
			_outputScroll = GUILayout.BeginScrollView(_outputScroll, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(num) });
			foreach (string item in _output)
			{
				GUILayout.Label(item, labelStyle, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndScrollView();
			GUILayout.Space(5f);
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(">", labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(12f) });
			GUI.SetNextControlName("ConsoleInput");
			_input = GUILayout.TextField(_input, textFieldStyle, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Execute", buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(70f) }))
			{
				Execute(_input);
				_input = "";
			}
			GUILayout.EndHorizontal();
			GUILayout.Label("Commands: spawn &lt;id&gt; [qty] | tp &lt;scene&gt; | time.set &lt;hour&gt; | reload.config", labelStyle, Array.Empty<GUILayoutOption>());
		}

		public void Execute(string command)
		{
			if (string.IsNullOrWhiteSpace(command))
			{
				return;
			}
			command = command.Trim();
			_history.Add(command);
			if (_history.Count > 50)
			{
				_history.RemoveAt(0);
			}
			_historyIndex = _history.Count;
			string[] array = command.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
			if (array.Length == 0)
			{
				return;
			}
			string text = array[0].ToLowerInvariant();
			try
			{
				switch (text)
				{
				case "spawn":
				{
					if (array.Length >= 2 && int.TryParse(array[1], out var result))
					{
						int result2;
						int num = ((array.Length < 3 || !int.TryParse(array[2], out result2)) ? 1 : result2);
						ItemInspector itemInspector = Pl