Decompiled source of HavenDevTools v1.0.2

HavenDevTools.dll

Decompiled 6 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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.Config;
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.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("HavenDevTools")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+c7976283ee1309608b00428a169c130e784344a0")]
[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 text = www.downloadHandler.text;
						string pattern = "\"" + Regex.Escape(pluginGuid) + "\"\\s*:\\s*\\{([^}]+)\\}";
						Match match = Regex.Match(text, pattern, RegexOptions.Singleline);
						if (!match.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 value = match.Groups[1].Value;
						result.LatestVersion = ExtractJsonString(value, "version");
						result.ModName = ExtractJsonString(value, "name");
						result.NexusUrl = ExtractJsonString(value, "nexus");
						result.Changelog = ExtractJsonString(value, "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);
				if (!match.Success)
				{
					return null;
				}
				return match.Groups[1].Value;
			}
		}

		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_000b: 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)
					{
						object obj = type2.MakeGenericType(type).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;
			}
			for (int i = 0; i < namespaces.Length; i++)
			{
				type = AccessTools.TypeByName(namespaces[i] + "." + 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" };
			foreach (string memberName in array)
			{
				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;
			}
		}
	}
}
namespace HavenDevTools
{
	[BepInPlugin("com.azraelgodking.havendevtools", "Haven Dev Tools", "1.0.1")]
	[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 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;

		private string _lastScene = "";

		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 IsAuthorized => _isAuthorized;

		public static string CurrentPlayerName => _currentPlayerName;

		private void Awake()
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: 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.1");
			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();
				CreateUIComponents();
				_harmony = new Harmony("com.azraelgodking.havendevtools");
				PatchPlayerInit();
				SceneManager.sceneLoaded += OnSceneLoaded;
				if (ModConfig.CheckForUpdates.Value)
				{
					VersionChecker.CheckForUpdate("com.azraelgodking.havendevtools", "1.0.1", 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}, HavensBirthright: {HasHavensBirthright}");
			}
			catch (Exception arg)
			{
				Log.LogError((object)string.Format("Failed to load {0}: {1}", "Haven Dev Tools", arg));
			}
		}

		private void CreatePersistentRunner()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: 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_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("HavenDevTools_UI");
			Object.DontDestroyOnLoad((Object)val);
			_staticDebugWindow = val.AddComponent<DebugWindow>();
			_staticDebugOverlay = val.AddComponent<DebugOverlay>();
			Log.LogInfo((object)"UI components created");
		}

		public static void EnsureUIComponentsExist()
		{
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: 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_00b7: Expected O, but got Unknown
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			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)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();
				}
			}
			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();
			for (int i = 0; i < assemblies.Length; i++)
			{
				string? name = assemblies[i].GetName().Name;
				if (name == "TheVault")
				{
					HasTheVault = true;
				}
				if (name == "SunHavenMuseumUtilityTracker")
				{
					HasSMUT = true;
				}
				if (name == "HavensBirthright")
				{
					HasHavensBirthright = true;
				}
			}
			Log.LogInfo((object)$"Mod detection complete - TheVault: {HasTheVault}, SMUT: {HasSMUT}, HavensBirthright: {HasHavensBirthright}");
		}

		private void PatchPlayerInit()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(Player), "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 Update()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			if (name != _lastScene)
			{
				Log.LogInfo((object)("[ScenePoll] Scene changed: '" + _lastScene + "' -> '" + name + "'"));
				_lastScene = name;
			}
		}

		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
				{
					_currentPlayerName = "Unknown";
				}
				_currentSteamId = TryGetSteamId();
				if (!string.IsNullOrEmpty(_currentSteamId))
				{
					string text = ComputeHash(_currentSteamId);
					if (_authorizedSteamIdHashes.Contains(text))
					{
						ManualLogSource log = Log;
						if (log != null)
						{
							log.LogInfo((object)"[HavenDevTools] Authorized via Steam ID");
						}
						_isAuthorized = true;
						return;
					}
					ManualLogSource log2 = Log;
					if (log2 != null)
					{
						log2.LogInfo((object)("[HavenDevTools] Steam ID hash not authorized: " + text));
					}
				}
				else
				{
					ManualLogSource log3 = Log;
					if (log3 != null)
					{
						log3.LogInfo((object)"[HavenDevTools] Could not retrieve Steam ID");
					}
				}
				ManualLogSource log4 = Log;
				if (log4 != null)
				{
					log4.LogInfo((object)"[HavenDevTools] Not authorized - Steam ID required");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log5 = Log;
				if (log5 != null)
				{
					log5.LogError((object)("[HavenDevTools] Authorization error: " + ex.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)
				{
					assemblies = AppDomain.CurrentDomain.GetAssemblies();
					foreach (Assembly assembly3 in assemblies)
					{
						try
						{
							if (assembly3.GetType("Steamworks.SteamUser") != null)
							{
								assembly = assembly3;
								break;
							}
						}
						catch
						{
						}
					}
				}
				if (assembly == null)
				{
					return null;
				}
				Type type = assembly.GetType("Steamworks.SteamUser");
				if (type == null)
				{
					return null;
				}
				MethodInfo method = type.GetMethod("GetSteamID", BindingFlags.Static | BindingFlags.Public);
				if (method == null)
				{
					return null;
				}
				object obj2 = method.Invoke(null, null);
				if (obj2 == null)
				{
					return null;
				}
				string text = obj2.ToString();
				if (string.IsNullOrEmpty(text) || text == "0" || text.Length < 10)
				{
					return null;
				}
				return text;
			}
			catch
			{
				return null;
			}
		}

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

		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 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 string _lastScene = "";

		private float _heartbeatTimer;

		private int _heartbeatCount;

		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();
			CheckSceneChange();
			_heartbeatTimer += Time.deltaTime;
			if (_heartbeatTimer >= 30f)
			{
				_heartbeatTimer = 0f;
				_heartbeatCount++;
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogInfo((object)string.Format("[PersistentRunner Heartbeat #{0}] Scene: {1}, Authorized: {2}, Player: {3}", _heartbeatCount, _lastScene, Plugin.IsAuthorized, Plugin.CurrentPlayerName ?? "none"));
				}
			}
		}

		private void CheckHotkeys()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: 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 CheckSceneChange()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			string name = ((Scene)(ref activeScene)).name;
			if (!(name != _lastScene))
			{
				return;
			}
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)("[PersistentRunner] Scene changed: '" + _lastScene + "' -> '" + name + "'"));
			}
			_lastScene = name;
			string text = name.ToLowerInvariant();
			if (text.Contains("menu") || text.Contains("title"))
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogInfo((object)"[PersistentRunner] Menu scene detected");
				}
			}
		}

		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.1";
	}
}
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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: 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)
			try
			{
				_playerName = Plugin.CurrentPlayerName ?? "Unknown";
				_currentRace = Plugin.GetRaceModifierTracker()?.GetCurrentRace() ?? "Unknown";
				_gold = Plugin.GetCurrencyTracker()?.GetGold() ?? 0;
				GameItemInfo gameItemInfo = Plugin.GetItemInspector()?.GetHeldItem();
				_heldItemInfo = ((gameItemInfo != null) ? $"[{gameItemInfo.Id}] {gameItemInfo.Name}" : "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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			if (_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_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: 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_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			float num = 220f;
			float num2 = 130f;
			float num3 = 10f;
			return (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), 
			});
		}

		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);
			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[5] { "Items", "Currencies", "Bundles", "Race Bonuses", "Utility" };

		private string _itemSearchText = "";

		private string _itemIdInput = "";

		private string _spawnAmount = "1";

		private List<GameItemInfo> _searchResults = new List<GameItemInfo>();

		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)[6]
		{
			("com.azraelgodking.havendevtools", "Haven Dev Tools", "1.0.1"),
			("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")
		};

		private const string PAUSE_ID = "HavenDevTools_Debug";

		private void Awake()
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			_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_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Expected O, but got Unknown
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: 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_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Expected O, but got Unknown
			//IL_0109: Expected O, but got Unknown
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: 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_0196: Expected O, but got Unknown
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: 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_01c0: 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_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Expected O, but got Unknown
			//IL_01fa: Expected O, but got Unknown
			//IL_0205: Unknown result type (might be due to invalid IL or missing references)
			//IL_020a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0212: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Expected O, but got Unknown
			//IL_0241: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_024e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Expected O, but got Unknown
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0273: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: 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_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: 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(120f) });
			GUILayout.Label("SMUT: " + (Plugin.HasSMUT ? "Yes" : "No"), _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) });
			GUILayout.Label("Birthright: " + (Plugin.HasHavensBirthright ? "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:
				DrawItemsTab();
				break;
			case 1:
				DrawCurrenciesTab();
				break;
			case 2:
				DrawBundlesTab();
				break;
			case 3:
				DrawRaceBonusesTab();
				break;
			case 4:
				DrawUtilityTab();
				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 DrawItemsTab()
		{
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01be: 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);
			GameItemInfo gameItemInfo = Plugin.GetItemInspector()?.GetHeldItem();
			if (gameItemInfo != null)
			{
				GUILayout.Label($"Held Item: [{gameItemInfo.Id}] {gameItemInfo.Name}", _labelStyle, Array.Empty<GUILayoutOption>());
			}
			else
			{
				GUILayout.Label("Held Item: None", _labelStyle, Array.Empty<GUILayoutOption>());
			}
			GUILayout.Space(10f);
			GUILayout.Label("Search Items:", _labelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			_itemSearchText = GUILayout.TextField(_itemSearchText, _textFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(250f) });
			if (GUILayout.Button("Search", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) }))
			{
				_searchResults = Plugin.GetItemInspector()?.SearchByName(_itemSearchText) ?? new List<GameItemInfo>();
			}
			if (GUILayout.Button("Clear", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
			{
				_itemSearchText = "";
				_searchResults.Clear();
			}
			GUILayout.EndHorizontal();
			if (_searchResults.Count > 0)
			{
				GUILayout.Label($"Results ({_searchResults.Count}):", _labelStyle, Array.Empty<GUILayoutOption>());
				_itemScrollPosition = GUILayout.BeginScrollView(_itemScrollPosition, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(150f) });
				foreach (GameItemInfo searchResult in _searchResults)
				{
					GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
					GUILayout.Label($"[{searchResult.Id}] {searchResult.Name}", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(300f) });
					if (GUILayout.Button("Spawn", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(60f) }))
					{
						_itemIdInput = searchResult.Id.ToString();
					}
					GUILayout.EndHorizontal();
				}
				GUILayout.EndScrollView();
			}
			GUILayout.Space(10f);
			GUILayout.Label("Spawn Item:", _labelStyle, Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label("ID:", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(25f) });
			_itemIdInput = GUILayout.TextField(_itemIdInput, _textFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(80f) });
			GUILayout.Label("Qty:", _labelStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) });
			_spawnAmount = GUILayout.TextField(_spawnAmount, _textFieldStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(50f) });
			if (GUILayout.Button("1", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(25f) }))
			{
				_spawnAmount = "1";
			}
			if (GUILayout.Button("10", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) }))
			{
				_spawnAmount = "10";
			}
			if (GUILayout.Button("99", _buttonStyle, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(30f) }))
			{
				_spawnAmount = "99";
			}
			GUILayout.EndHorizontal();
			if (GUILayout.Button("Spawn to Inventory", _buttonStyle, Array.Empty<GUILayoutOption>()) && int.TryParse(_itemIdInput, out var result) && int.TryParse(_spawnAmount, out var result2))
			{
				Plugin.GetItemInspector()?.SpawnItem(result, result2);
			}
			GUILayout.EndVertical();
		}

		private void DrawCurrenciesTab()
		{
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			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_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c6: 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_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: 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);
			ItemInspector itemInspector = Plugin.GetItemInspector();
			GUILayout.Label(string.Format("Item Cache: {0} items ({1})", itemInspector?.CacheCount ?? 0, (itemInspector != null && itemInspector.IsCacheBuilt) ? "built" : "not built"), _labelStyle, Array.Empty<GUILayoutOption>());
			if (GUILayout.Button("Build Item Cache", _buttonStyle, Array.Empty<GUILayoutOption>()))
			{
				itemInspector?.BuildCache();
			}
			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>()))
			{
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogInfo((object)"Check BepInEx console for your Steam ID hash");
				}
			}
			GUILayout.EndVertical();
		}

		private void DrawVersionCheckerSection()
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_013d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Expected O, but got Unknown
			//IL_01dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Expected O, but got Unknown
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0197: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b8: 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 ===");
				}
				PropertyInfo[] properties = ((object)Player.Instance).GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
				foreach (PropertyInfo propertyInfo in properties)
				{
					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
					{
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log4 = Plugin.Log;
				if (log4 != null)
				{
					log4.LogError((object)("Error logging player stats: " + 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 && int.TryParse(match.Groups[1].Value.Replace(",", ""), 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 CurrencyTracker
	{
		public static readonly Dictionary<string, int> CurrencyItemIds = new Dictionary<string, int>
		{
			{ "Spring Token", 18020 },
			{ "Summer Token", 18021 },
			{ "Fall Token", 18023 },
			{ "Winter Token", 18022 },
			{ "Copper Key", 1251 },
			{ "Iron Key", 1252 },
			{ "Adamant Key", 1253 },
			{ "Mithril Key", 1254 },
			{ "Sunite Key", 1255 },
			{ "Glorite Key", 1256 },
			{ "King's Lost Mine Key", 1257 },
			{ "Community Token", 18013 },
			{ "Doubloon", 60014 },
			{ "Black Bottle Cap", 60013 },
			{ "Red Carnival Ticket", 18012 },
			{ "Candy Corn Pieces", 18016 },
			{ "Mana Shard", 18015 }
		};

		public CurrencyTracker()
		{
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"[CurrencyTracker] Initialized");
			}
		}

		public int GetInventoryAmount(int itemId)
		{
			try
			{
				Player instance = Player.Instance;
				if ((Object)(object)((instance != null) ? instance.Inventory : null) == (Object)null)
				{
					return 0;
				}
				Inventory inventory = Player.Instance.Inventory;
				MethodInfo methodInfo = AccessTools.Method(((object)inventory).GetType(), "GetAmount", new Type[1] { typeof(int) }, (Type[])null);
				if (methodInfo != null)
				{
					return (int)methodInfo.Invoke(inventory, new object[1] { itemId });
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[CurrencyTracker] Error getting inventory amount: " + ex.Message));
				}
			}
			return 0;
		}

		public int GetVaultAmount(string currencyId)
		{
			if (!Plugin.HasTheVault)
			{
				return 0;
			}
			try
			{
				Assembly vaultAssembly = GetVaultAssembly();
				if (vaultAssembly == null)
				{
					return 0;
				}
				Type type = vaultAssembly.GetType("TheVault.Plugin");
				if (type == null)
				{
					return 0;
				}
				MethodInfo method = type.GetMethod("GetVaultManager", BindingFlags.Static | BindingFlags.Public);
				if (method == null)
				{
					return 0;
				}
				object obj = method.Invoke(null, null);
				if (obj == null)
				{
					return 0;
				}
				MethodInfo method2 = obj.GetType().GetMethod("GetCurrency", new Type[1] { typeof(string) });
				if (method2 != null)
				{
					return (int)method2.Invoke(obj, new object[1] { currencyId });
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[CurrencyTracker] Error getting vault amount: " + ex.Message));
				}
			}
			return 0;
		}

		public Dictionary<string, int> GetAllVaultCurrencies()
		{
			Dictionary<string, int> result = new Dictionary<string, int>();
			if (!Plugin.HasTheVault)
			{
				return result;
			}
			try
			{
				Assembly vaultAssembly = GetVaultAssembly();
				if (vaultAssembly == null)
				{
					return result;
				}
				Type type = vaultAssembly.GetType("TheVault.Plugin");
				if (type == null)
				{
					return result;
				}
				MethodInfo method = type.GetMethod("GetVaultManager", BindingFlags.Static | BindingFlags.Public);
				if (method == null)
				{
					return result;
				}
				object obj = method.Invoke(null, null);
				if (obj == null)
				{
					return result;
				}
				MethodInfo method2 = obj.GetType().GetMethod("GetAllNonZeroCurrencies");
				if (method2 != null && method2.Invoke(obj, null) is Dictionary<string, int> result2)
				{
					return result2;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[CurrencyTracker] Error getting all vault currencies: " + ex.Message));
				}
			}
			return result;
		}

		public int GetGold()
		{
			try
			{
				Type type = AccessTools.TypeByName("Wish.GameSave");
				if (type != null)
				{
					PropertyInfo property = type.GetProperty("Coins", BindingFlags.Static | BindingFlags.Public);
					if (property != null)
					{
						return (int)property.GetValue(null);
					}
				}
				Type type2 = AccessTools.TypeByName("SingletonBehaviour`1");
				if (type2 != null && type != null)
				{
					PropertyInfo property2 = type2.MakeGenericType(type).GetProperty("Instance", BindingFlags.Static | BindingFlags.Public);
					if (property2 != null)
					{
						object value = property2.GetValue(null);
						if (value != null)
						{
							PropertyInfo property3 = value.GetType().GetProperty("CurrentSave");
							if (property3 != null)
							{
								object value2 = property3.GetValue(value);
								if (value2 != null)
								{
									FieldInfo field = value2.GetType().GetField("coins", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
									if (field != null)
									{
										return Convert.ToInt32(field.GetValue(value2));
									}
								}
							}
						}
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[CurrencyTracker] Error getting gold: " + ex.Message));
				}
			}
			return 0;
		}

		public int GetOrbs()
		{
			try
			{
				if ((Object)(object)Player.Instance == (Object)null)
				{
					return 0;
				}
				PropertyInfo property = ((object)Player.Instance).GetType().GetProperty("Orbs", BindingFlags.Instance | BindingFlags.Public);
				if (property != null)
				{
					return (int)property.GetValue(Player.Instance);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[CurrencyTracker] Error getting orbs: " + ex.Message));
				}
			}
			return 0;
		}

		public int GetTickets()
		{
			try
			{
				if ((Object)(object)Player.Instance == (Object)null)
				{
					return 0;
				}
				PropertyInfo property = ((object)Player.Instance).GetType().GetProperty("Tickets", BindingFlags.Instance | BindingFlags.Public);
				if (property != null)
				{
					return (int)property.GetValue(Player.Instance);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[CurrencyTracker] Error getting tickets: " + ex.Message));
				}
			}
			return 0;
		}

		public CurrencySummary GetSummary()
		{
			CurrencySummary currencySummary = new CurrencySummary
			{
				Gold = GetGold(),
				Orbs = GetOrbs(),
				Tickets = GetTickets(),
				InventoryCurrencies = new Dictionary<string, int>(),
				VaultCurrencies = new Dictionary<string, int>()
			};
			foreach (KeyValuePair<string, int> currencyItemId in CurrencyItemIds)
			{
				int inventoryAmount = GetInventoryAmount(currencyItemId.Value);
				if (inventoryAmount > 0)
				{
					currencySummary.InventoryCurrencies[currencyItemId.Key] = inventoryAmount;
				}
			}
			if (Plugin.HasTheVault)
			{
				currencySummary.VaultCurrencies = GetAllVaultCurrencies();
			}
			return currencySummary;
		}

		private Assembly GetVaultAssembly()
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				if (assembly.GetName().Name == "TheVault")
				{
					return assembly;
				}
			}
			return null;
		}
	}
	public class CurrencySummary
	{
		public int Gold { get; set; }

		public int Orbs { get; set; }

		public int Tickets { get; set; }

		public Dictionary<string, int> InventoryCurrencies { get; set; }

		public Dictionary<string, int> VaultCurrencies { get; set; }
	}
	public class ItemInspector
	{
		private Dictionary<int, GameItemInfo> _itemCache = new Dictionary<int, GameItemInfo>();

		private Dictionary<string, int> _nameToIdCache = new Dictionary<string, int>(StringComparer.OrdinalIgnoreCase);

		private bool _cacheBuilt;

		public int CacheCount => _itemCache.Count;

		public bool IsCacheBuilt => _cacheBuilt;

		public ItemInspector()
		{
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"[ItemInspector] Initialized");
			}
		}

		public void BuildCache()
		{
			if (_cacheBuilt)
			{
				return;
			}
			try
			{
				Type type = AccessTools.TypeByName("Wish.ItemDatabase") ?? AccessTools.TypeByName("ItemDatabase");
				if (type == null)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)"[ItemInspector] Could not find ItemDatabase type");
					}
					return;
				}
				PropertyInfo property = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public);
				if (property == null)
				{
					ManualLogSource log2 = Plugin.Log;
					if (log2 != null)
					{
						log2.LogWarning((object)"[ItemInspector] Could not find ItemDatabase.Instance");
					}
					return;
				}
				object value = property.GetValue(null);
				if (value == null)
				{
					ManualLogSource log3 = Plugin.Log;
					if (log3 != null)
					{
						log3.LogWarning((object)"[ItemInspector] ItemDatabase.Instance is null");
					}
					return;
				}
				FieldInfo field = type.GetField("items", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field == null)
				{
					field = type.GetField("_items", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				}
				if (field != null)
				{
					object value2 = field.GetValue(value);
					if (value2 is IDictionary<int, object> dictionary)
					{
						foreach (KeyValuePair<int, object> item in dictionary)
						{
							CacheItem(item.Key, item.Value);
						}
					}
					else if (value2 is IEnumerable enumerable)
					{
						foreach (object item2 in enumerable)
						{
							PropertyInfo propertyInfo = item2.GetType().GetProperty("id") ?? item2.GetType().GetProperty("ID");
							if (propertyInfo != null)
							{
								int id = (int)propertyInfo.GetValue(item2);
								CacheItem(id, item2);
							}
						}
					}
				}
				_cacheBuilt = true;
				ManualLogSource log4 = Plugin.Log;
				if (log4 != null)
				{
					log4.LogInfo((object)$"[ItemInspector] Built cache with {_itemCache.Count} items");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log5 = Plugin.Log;
				if (log5 != null)
				{
					log5.LogError((object)("[ItemInspector] Error building cache: " + ex.Message));
				}
			}
		}

		private void CacheItem(int id, object item)
		{
			try
			{
				Type type = item.GetType();
				PropertyInfo? obj = type.GetProperty("name") ?? type.GetProperty("Name") ?? type.GetProperty("itemName");
				PropertyInfo propertyInfo = type.GetProperty("description") ?? type.GetProperty("Description");
				PropertyInfo propertyInfo2 = type.GetProperty("category") ?? type.GetProperty("Category");
				PropertyInfo propertyInfo3 = type.GetProperty("sellPrice") ?? type.GetProperty("SellPrice");
				string text = obj?.GetValue(item)?.ToString() ?? "Unknown";
				string description = propertyInfo?.GetValue(item)?.ToString() ?? "";
				string category = propertyInfo2?.GetValue(item)?.ToString() ?? "Unknown";
				int sellPrice = ((propertyInfo3 != null) ? Convert.ToInt32(propertyInfo3.GetValue(item)) : 0);
				GameItemInfo value = new GameItemInfo
				{
					Id = id,
					Name = text,
					Description = description,
					Category = category,
					SellPrice = sellPrice
				};
				_itemCache[id] = value;
				if (!_nameToIdCache.ContainsKey(text))
				{
					_nameToIdCache[text] = id;
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)$"[ItemInspector] Error caching item {id}: {ex.Message}");
				}
			}
		}

		public GameItemInfo GetItemById(int id)
		{
			if (!_cacheBuilt)
			{
				BuildCache();
			}
			if (_itemCache.TryGetValue(id, out var value))
			{
				return value;
			}
			return TryGetItemFromDatabase(id);
		}

		public List<GameItemInfo> SearchByName(string searchTerm)
		{
			if (!_cacheBuilt)
			{
				BuildCache();
			}
			List<GameItemInfo> list = new List<GameItemInfo>();
			string value = searchTerm.ToLower();
			foreach (GameItemInfo value2 in _itemCache.Values)
			{
				if (value2.Name.ToLower().Contains(value))
				{
					list.Add(value2);
				}
			}
			return list;
		}

		public int? GetIdByName(string name)
		{
			if (!_cacheBuilt)
			{
				BuildCache();
			}
			if (_nameToIdCache.TryGetValue(name, out var value))
			{
				return value;
			}
			return null;
		}

		public IEnumerable<GameItemInfo> GetAllItems()
		{
			if (!_cacheBuilt)
			{
				BuildCache();
			}
			return _itemCache.Values;
		}

		public GameItemInfo GetHeldItem()
		{
			try
			{
				if ((Object)(object)Player.Instance == (Object)null || (Object)(object)Player.Instance.Inventory == (Object)null)
				{
					return null;
				}
				Inventory inventory = Player.Instance.Inventory;
				Type type = ((object)inventory).GetType();
				int num = 0;
				PropertyInfo propertyInfo = type.GetProperty("SelectedSlot") ?? type.GetProperty("selectedSlot");
				if (propertyInfo != null)
				{
					num = (int)propertyInfo.GetValue(inventory);
				}
				else
				{
					FieldInfo field = type.GetField("selectedSlot", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(field != null))
					{
						return null;
					}
					num = (int)field.GetValue(inventory);
				}
				MethodInfo methodInfo = AccessTools.Method(((object)inventory).GetType(), "GetItem", new Type[1] { typeof(int) }, (Type[])null);
				if (methodInfo != null)
				{
					object obj = methodInfo.Invoke(inventory, new object[1] { num });
					if (obj != null)
					{
						PropertyInfo propertyInfo2 = obj.GetType().GetProperty("id") ?? obj.GetType().GetProperty("ID");
						if (propertyInfo2 != null)
						{
							int id = (int)propertyInfo2.GetValue(obj);
							return GetItemById(id);
						}
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[ItemInspector] Error getting held item: " + ex.Message));
				}
			}
			return null;
		}

		private GameItemInfo TryGetItemFromDatabase(int id)
		{
			try
			{
				Type type = AccessTools.TypeByName("Wish.ItemDatabase") ?? AccessTools.TypeByName("ItemDatabase");
				if (type == null)
				{
					return null;
				}
				MethodInfo methodInfo = AccessTools.Method(type, "GetItem", new Type[1] { typeof(int) }, (Type[])null);
				if (methodInfo == null)
				{
					return null;
				}
				object obj = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public)?.GetValue(null);
				if (obj == null)
				{
					return null;
				}
				object obj2 = methodInfo.Invoke(obj, new object[1] { id });
				if (obj2 != null)
				{
					CacheItem(id, obj2);
					GameItemInfo value;
					return _itemCache.TryGetValue(id, out value) ? value : null;
				}
			}
			catch
			{
			}
			return null;
		}

		public bool SpawnItem(int itemId, int amount = 1)
		{
			try
			{
				if ((Object)(object)Player.Instance == (Object)null || (Object)(object)Player.Instance.Inventory == (Object)null)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogWarning((object)"[ItemInspector] Player or inventory not available");
					}
					return false;
				}
				Inventory inventory = Player.Instance.Inventory;
				MethodInfo methodInfo = AccessTools.Method(((object)inventory).GetType(), "AddItem", new Type[3]
				{
					typeof(int),
					typeof(int),
					typeof(bool)
				}, (Type[])null);
				if (methodInfo != null)
				{
					methodInfo.Invoke(inventory, new object[3] { itemId, amount, true });
					ManualLogSource log2 = Plugin.Log;
					if (log2 != null)
					{
						log2.LogInfo((object)$"[ItemInspector] Spawned {amount}x item {itemId}");
					}
					return true;
				}
				ManualLogSource log3 = Plugin.Log;
				if (log3 != null)
				{
					log3.LogWarning((object)"[ItemInspector] Could not find AddItem method");
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log4 = Plugin.Log;
				if (log4 != null)
				{
					log4.LogError((object)("[ItemInspector] Spawn error: " + ex.Message));
				}
			}
			return false;
		}
	}
	public class GameItemInfo
	{
		public int Id { get; set; }

		public string Name { get; set; }

		public string Description { get; set; }

		public string Category { get; set; }

		public int SellPrice { get; set; }

		public override string ToString()
		{
			return $"[{Id}] {Name} ({Category}) - {SellPrice}g";
		}
	}
	public class RaceModifierTracker
	{
		public RaceModifierTracker()
		{
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)"[RaceModifierTracker] Initialized");
			}
		}

		public string GetCurrentRace()
		{
			if (!Plugin.HasHavensBirthright)
			{
				return "Unknown (Haven's Birthright not loaded)";
			}
			try
			{
				Assembly birthrightAssembly = GetBirthrightAssembly();
				if (birthrightAssembly == null)
				{
					return "Unknown";
				}
				Type type = birthrightAssembly.GetType("HavensBirthright.Plugin");
				if (type == null)
				{
					return "Unknown";
				}
				MethodInfo method = type.GetMethod("GetRacialBonusManager", BindingFlags.Static | BindingFlags.Public);
				if (method == null)
				{
					return "Unknown";
				}
				object obj = method.Invoke(null, null);
				if (obj == null)
				{
					return "Unknown";
				}
				MethodInfo method2 = obj.GetType().GetMethod("GetPlayerRace");
				if (method2 != null)
				{
					object obj2 = method2.Invoke(obj, null);
					if (obj2 != null)
					{
						return obj2.ToString();
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[RaceModifierTracker] Error getting race: " + ex.Message));
				}
			}
			return "Unknown";
		}

		public List<RaceBonusInfo> GetActiveRaceBonuses()
		{
			List<RaceBonusInfo> list = new List<RaceBonusInfo>();
			if (!Plugin.HasHavensBirthright)
			{
				return list;
			}
			try
			{
				Assembly birthrightAssembly = GetBirthrightAssembly();
				if (birthrightAssembly == null)
				{
					return list;
				}
				Type type = birthrightAssembly.GetType("HavensBirthright.Plugin");
				if (type == null)
				{
					return list;
				}
				MethodInfo method = type.GetMethod("GetRacialBonusManager", BindingFlags.Static | BindingFlags.Public);
				if (method == null)
				{
					return list;
				}
				object obj = method.Invoke(null, null);
				if (obj == null)
				{
					return list;
				}
				MethodInfo method2 = obj.GetType().GetMethod("GetCurrentPlayerBonuses");
				if (method2 == null)
				{
					return list;
				}
				if (!(method2.Invoke(obj, null) is IList list2))
				{
					return list;
				}
				foreach (object item2 in list2)
				{
					Type type2 = item2.GetType();
					PropertyInfo property = type2.GetProperty("Type");
					PropertyInfo property2 = type2.GetProperty("Value");
					PropertyInfo property3 = type2.GetProperty("IsPercentage");
					PropertyInfo property4 = type2.GetProperty("Description");
					RaceBonusInfo item = new RaceBonusInfo
					{
						Type = (property?.GetValue(item2)?.ToString() ?? "Unknown"),
						Value = ((property2 != null) ? Convert.ToSingle(property2.GetValue(item2)) : 0f),
						IsPercentage = (property3 != null && (bool)property3.GetValue(item2)),
						Description = (property4?.GetValue(item2)?.ToString() ?? "")
					};
					list.Add(item);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[RaceModifierTracker] Error getting bonuses: " + ex.Message));
				}
			}
			return list;
		}

		public List<RaceBonusInfo> GetBonusesForRace(string raceName)
		{
			List<RaceBonusInfo> list = new List<RaceBonusInfo>();
			if (!Plugin.HasHavensBirthright)
			{
				return list;
			}
			try
			{
				Assembly birthrightAssembly = GetBirthrightAssembly();
				if (birthrightAssembly == null)
				{
					return list;
				}
				Type type = birthrightAssembly.GetType("HavensBirthright.Plugin");
				if (type == null)
				{
					return list;
				}
				MethodInfo method = type.GetMethod("GetRacialBonusManager", BindingFlags.Static | BindingFlags.Public);
				if (method == null)
				{
					return list;
				}
				object obj = method.Invoke(null, null);
				if (obj == null)
				{
					return list;
				}
				Type type2 = birthrightAssembly.GetType("HavensBirthright.Race");
				if (type2 == null)
				{
					return list;
				}
				object obj2;
				try
				{
					obj2 = Enum.Parse(type2, raceName, ignoreCase: true);
				}
				catch
				{
					return list;
				}
				MethodInfo method2 = obj.GetType().GetMethod("GetBonusesForRace");
				if (method2 == null)
				{
					return list;
				}
				if (!(method2.Invoke(obj, new object[1] { obj2 }) is IList list2))
				{
					return list;
				}
				foreach (object item2 in list2)
				{
					Type type3 = item2.GetType();
					PropertyInfo property = type3.GetProperty("Type");
					PropertyInfo property2 = type3.GetProperty("Value");
					PropertyInfo property3 = type3.GetProperty("IsPercentage");
					PropertyInfo property4 = type3.GetProperty("Description");
					RaceBonusInfo item = new RaceBonusInfo
					{
						Type = (property?.GetValue(item2)?.ToString() ?? "Unknown"),
						Value = ((property2 != null) ? Convert.ToSingle(property2.GetValue(item2)) : 0f),
						IsPercentage = (property3 != null && (bool)property3.GetValue(item2)),
						Description = (property4?.GetValue(item2)?.ToString() ?? "")
					};
					list.Add(item);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("[RaceModifierTracker] Error getting bonuses for race: " + ex.Message));
				}
			}
			return list;
		}

		public List<string> GetAllRaces()
		{
			List<string> list = new List<string>();
			if (!Plugin.HasHavensBirthright)
			{
				return new List<string>
				{
					"Human", "Elf", "Angel", "Demon", "Elemental", "FireElemental", "WaterElemental", "Amari", "AmariCat", "AmariDog",
					"AmariBird", "AmariAquatic", "AmariReptile", "Naga"
				};
			}
			try
			{
				Ass