Decompiled source of MonsterGuide v1.0.0

BepInEx\plugins\MonsterGuide\MonsterGuide.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("MechGaming")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("MonsterGuide")]
[assembly: AssemblyTitle("MonsterGuide")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace MechGaming.REPO.MonsterGuide
{
	internal static class HotkeyInput
	{
		private const int KeyDownMask = 32768;

		private const float TextInputScanInterval = 0.15f;

		private static readonly Dictionary<KeyCode, bool> PreviousStates = new Dictionary<KeyCode, bool>();

		private static readonly Type? UnityInputFieldType = Type.GetType("UnityEngine.UI.InputField, UnityEngine.UI");

		private static readonly Type? TmpInputFieldType = Type.GetType("TMPro.TMP_InputField, Unity.TextMeshPro");

		private static int _currentProcessId;

		private static float _nextTextInputScanTime;

		private static bool _cachedNoTextInputActive = true;

		private static int CurrentProcessId
		{
			get
			{
				if (_currentProcessId == 0)
				{
					_currentProcessId = Process.GetCurrentProcess().Id;
				}
				return _currentProcessId;
			}
		}

		internal static bool GetKeyDown(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if ((int)key == 0)
			{
				return false;
			}
			bool flag = GetUnityKeyDown(key) || GetWindowsKey(key);
			bool value;
			bool flag2 = PreviousStates.TryGetValue(key, out value) && value;
			PreviousStates[key] = flag;
			if (flag)
			{
				return !flag2;
			}
			return false;
		}

		internal static bool NoTextInputActive()
		{
			if (Time.unscaledTime < _nextTextInputScanTime)
			{
				return _cachedNoTextInputActive;
			}
			_nextTextInputScanTime = Time.unscaledTime + 0.15f;
			_cachedNoTextInputActive = !AnyFocusedTextInput();
			return _cachedNoTextInputActive;
		}

		private static bool GetUnityKeyDown(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				return Input.GetKeyDown(key);
			}
			catch
			{
				return false;
			}
		}

		private static bool GetWindowsKey(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			int num = ToVirtualKey(key);
			if (num != 0 && IsForegroundProcess())
			{
				return IsVirtualKeyDown(num);
			}
			return false;
		}

		private static bool IsVirtualKeyDown(int virtualKey)
		{
			try
			{
				return (GetAsyncKeyState(virtualKey) & 0x8000) != 0;
			}
			catch
			{
				return false;
			}
		}

		private static bool IsForegroundProcess()
		{
			try
			{
				IntPtr foregroundWindow = GetForegroundWindow();
				if (foregroundWindow == IntPtr.Zero)
				{
					return false;
				}
				GetWindowThreadProcessId(foregroundWindow, out var processId);
				return processId == CurrentProcessId;
			}
			catch
			{
				return false;
			}
		}

		private static int ToVirtualKey(KeyCode key)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Invalid comparison between Unknown and I4
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Expected I4, but got Unknown
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Invalid comparison between Unknown and I4
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Invalid comparison between Unknown and I4
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected I4, but got Unknown
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Invalid comparison between Unknown and I4
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Invalid comparison between Unknown and I4
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected I4, but got Unknown
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected I4, but got Unknown
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Invalid comparison between Unknown and I4
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Invalid comparison between Unknown and I4
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Invalid comparison between Unknown and I4
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Expected I4, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Invalid comparison between Unknown and I4
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Invalid comparison between Unknown and I4
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Invalid comparison between Unknown and I4
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected I4, but got Unknown
			if ((int)key >= 97 && (int)key <= 122)
			{
				return 65 + (key - 97);
			}
			if ((int)key >= 48 && (int)key <= 57)
			{
				return 48 + (key - 48);
			}
			if ((int)key >= 282 && (int)key <= 678)
			{
				return 112 + (key - 282);
			}
			if ((int)key <= 27)
			{
				if ((int)key <= 9)
				{
					if ((int)key == 8)
					{
						return 8;
					}
					if ((int)key == 9)
					{
						return 9;
					}
				}
				else
				{
					if ((int)key == 13)
					{
						return 13;
					}
					if ((int)key == 27)
					{
						return 27;
					}
				}
			}
			else if ((int)key <= 127)
			{
				if ((int)key == 32)
				{
					return 32;
				}
				if ((int)key == 127)
				{
					return 46;
				}
			}
			else
			{
				switch (key - 273)
				{
				case 7:
					return 33;
				case 8:
					return 34;
				case 6:
					return 35;
				case 5:
					return 36;
				case 3:
					return 37;
				case 0:
					return 38;
				case 2:
					return 39;
				case 1:
					return 40;
				case 4:
					return 45;
				}
				switch (key - 303)
				{
				case 1:
					return 160;
				case 0:
					return 161;
				case 3:
					return 162;
				case 2:
					return 163;
				case 5:
					return 164;
				case 4:
					return 165;
				}
				switch (key - 323)
				{
				case 0:
					return 1;
				case 1:
					return 2;
				case 2:
					return 4;
				}
			}
			return 0;
		}

		private static bool AnyFocusedTextInput()
		{
			if (!TypeHasFocusedInput(UnityInputFieldType))
			{
				return TypeHasFocusedInput(TmpInputFieldType);
			}
			return true;
		}

		private static bool TypeHasFocusedInput(Type? inputType)
		{
			if (inputType == null)
			{
				return false;
			}
			try
			{
				Object[] array = Resources.FindObjectsOfTypeAll(inputType);
				for (int i = 0; i < array.Length; i++)
				{
					if (IsFocusedInput(array[i]))
					{
						return true;
					}
				}
			}
			catch
			{
				return false;
			}
			return false;
		}

		private static bool IsFocusedInput(Object input)
		{
			Component val = (Component)(object)((input is Component) ? input : null);
			if (val == null || !val.gameObject.activeInHierarchy)
			{
				return false;
			}
			Behaviour val2 = (Behaviour)(object)((val is Behaviour) ? val : null);
			if (val2 != null && !val2.enabled)
			{
				return false;
			}
			PropertyInfo property = ((object)input).GetType().GetProperty("isFocused", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property == null || property.PropertyType != typeof(bool))
			{
				return false;
			}
			try
			{
				return (bool)property.GetValue(input, null);
			}
			catch
			{
				return false;
			}
		}

		[DllImport("user32.dll")]
		private static extern short GetAsyncKeyState(int virtualKey);

		[DllImport("user32.dll")]
		private static extern IntPtr GetForegroundWindow();

		[DllImport("user32.dll")]
		private static extern uint GetWindowThreadProcessId(IntPtr windowHandle, out uint processId);
	}
	internal sealed class ImageLoader
	{
		private readonly string _imagesDirectory;

		private readonly ManualLogSource _logger;

		private readonly Dictionary<string, Texture2D?> _cache = new Dictionary<string, Texture2D>(StringComparer.OrdinalIgnoreCase);

		internal string ImagesDirectory => _imagesDirectory;

		internal int ExpectedCount { get; private set; }

		internal int LoadedCount { get; private set; }

		internal int MissingCount { get; private set; }

		internal ImageLoader(string imagesDirectory, ManualLogSource logger)
		{
			_imagesDirectory = imagesDirectory;
			_logger = logger;
			_logger.LogInfo((object)("[MonsterGuide] Image path: " + _imagesDirectory));
		}

		internal void Preload(IReadOnlyList<MonsterRecord> monsters)
		{
			ExpectedCount = monsters.Count;
			LoadedCount = 0;
			MissingCount = 0;
			foreach (MonsterRecord monster in monsters)
			{
				if ((Object)(object)GetTexture(monster) != (Object)null)
				{
					LoadedCount++;
				}
				else
				{
					MissingCount++;
				}
			}
			_logger.LogInfo((object)$"[MonsterGuide] Loaded images: {LoadedCount} / {ExpectedCount}");
			if (MissingCount > 0)
			{
				_logger.LogWarning((object)$"[MonsterGuide] Missing images: {MissingCount} / {ExpectedCount}");
			}
		}

		internal Texture2D? GetTexture(MonsterRecord monster)
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Expected O, but got Unknown
			string text = (string.IsNullOrWhiteSpace(monster.image) ? (monster.id + ".png") : monster.image);
			if (!IsSafeFileName(text))
			{
				_logger.LogWarning((object)("Ignoring unsafe MonsterGuide image filename '" + text + "' for " + monster.id + "."));
				return null;
			}
			string text2 = Path.Combine(_imagesDirectory, text);
			if (_cache.TryGetValue(text2, out Texture2D value))
			{
				return value;
			}
			_logger.LogInfo((object)("[MonsterGuide] Trying image for " + monster.name + ": " + text2));
			if (!File.Exists(text2))
			{
				_cache[text2] = null;
				_logger.LogWarning((object)("[MonsterGuide] Missing image for " + monster.name + ": " + text));
				return null;
			}
			try
			{
				byte[] array = File.ReadAllBytes(text2);
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false)
				{
					name = "MonsterGuide_" + monster.id,
					hideFlags = (HideFlags)61
				};
				if (!ImageConversion.LoadImage(val, array))
				{
					Object.Destroy((Object)(object)val);
					_cache[text2] = null;
					_logger.LogWarning((object)("[MonsterGuide] Could not decode image for " + monster.name + ": " + text));
					return null;
				}
				_cache[text2] = val;
				_logger.LogInfo((object)("[MonsterGuide] Loaded image for " + monster.name + ": " + text));
				return val;
			}
			catch (Exception ex)
			{
				_cache[text2] = null;
				_logger.LogWarning((object)("[MonsterGuide] Could not load image for " + monster.name + " from " + text2 + ": " + ex.Message));
				return null;
			}
		}

		internal void DestroyAll()
		{
			foreach (Texture2D value in _cache.Values)
			{
				if ((Object)(object)value != (Object)null)
				{
					Object.Destroy((Object)(object)value);
				}
			}
			_cache.Clear();
		}

		private static bool IsSafeFileName(string fileName)
		{
			if (!string.IsNullOrWhiteSpace(fileName) && fileName.IndexOfAny(Path.GetInvalidFileNameChars()) < 0 && !fileName.Contains(".."))
			{
				if (!fileName.EndsWith(".png", StringComparison.OrdinalIgnoreCase) && !fileName.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase))
				{
					return fileName.EndsWith(".jpeg", StringComparison.OrdinalIgnoreCase);
				}
				return true;
			}
			return false;
		}
	}
	internal static class InputBlocker
	{
		private static readonly HashSet<MethodBase> PatchedMethods = new HashSet<MethodBase>();

		private static Harmony? _harmony;

		private static ManualLogSource? _logger;

		internal static void Init(ManualLogSource logger)
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Expected O, but got Unknown
			_logger = logger;
			if (_harmony == null)
			{
				_harmony = new Harmony("mechgaming13.MonsterGuide.InputBlocker");
			}
		}

		internal static void PatchAvailableHotkeyReaders()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			if (_harmony == null)
			{
				return;
			}
			HarmonyMethod val = new HarmonyMethod(typeof(InputBlocker), "BlockExternalHotkeyPostfix", (Type[])null);
			int num = 0;
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				if (assembly == typeof(InputBlocker).Assembly)
				{
					continue;
				}
				foreach (Type safeType in GetSafeTypes(assembly))
				{
					if (!string.Equals(safeType.Name, "HotkeyInput", StringComparison.Ordinal))
					{
						continue;
					}
					MethodInfo method = safeType.GetMethod("GetKeyDown", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(KeyCode) }, null);
					if (method == null || method.ReturnType != typeof(bool) || PatchedMethods.Contains(method))
					{
						continue;
					}
					try
					{
						_harmony.Patch((MethodBase)method, (HarmonyMethod)null, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
						PatchedMethods.Add(method);
						num++;
						ManualLogSource? logger = _logger;
						if (logger != null)
						{
							logger.LogInfo((object)("[MonsterGuide] Blocking external hotkeys while open: " + safeType.FullName + "." + method.Name));
						}
					}
					catch (Exception ex)
					{
						ManualLogSource? logger2 = _logger;
						if (logger2 != null)
						{
							logger2.LogDebug((object)("[MonsterGuide] Could not patch hotkey reader " + safeType.FullName + ": " + ex.Message));
						}
					}
				}
			}
			if (num > 0)
			{
				ManualLogSource? logger3 = _logger;
				if (logger3 != null)
				{
					logger3.LogInfo((object)$"[MonsterGuide] Patched {num} external hotkey reader(s).");
				}
			}
		}

		internal static void Unpatch()
		{
			Harmony? harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			PatchedMethods.Clear();
		}

		private static void BlockExternalHotkeyPostfix(ref bool __result)
		{
			if (Plugin.GuideOpen)
			{
				__result = false;
			}
		}

		private static IEnumerable<Type> GetSafeTypes(Assembly assembly)
		{
			try
			{
				return assembly.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				return ex.Types.WhereNotNull();
			}
			catch
			{
				return Array.Empty<Type>();
			}
		}
	}
	internal static class TypeEnumerableExtensions
	{
		[CompilerGenerated]
		private sealed class <WhereNotNull>d__0 : IEnumerable<Type>, IEnumerable, IEnumerator<Type>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private Type <>2__current;

			private int <>l__initialThreadId;

			private IEnumerable<Type?> types;

			public IEnumerable<Type?> <>3__types;

			private IEnumerator<Type?> <>7__wrap1;

			Type IEnumerator<Type>.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			object IEnumerator.Current
			{
				[DebuggerHidden]
				get
				{
					return <>2__current;
				}
			}

			[DebuggerHidden]
			public <WhereNotNull>d__0(int <>1__state)
			{
				this.<>1__state = <>1__state;
				<>l__initialThreadId = Environment.CurrentManagedThreadId;
			}

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				int num = <>1__state;
				if (num == -3 || num == 1)
				{
					try
					{
					}
					finally
					{
						<>m__Finally1();
					}
				}
				<>7__wrap1 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				try
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						<>7__wrap1 = types.GetEnumerator();
						<>1__state = -3;
						break;
					case 1:
						<>1__state = -3;
						break;
					}
					while (<>7__wrap1.MoveNext())
					{
						Type current = <>7__wrap1.Current;
						if (current != null)
						{
							<>2__current = current;
							<>1__state = 1;
							return true;
						}
					}
					<>m__Finally1();
					<>7__wrap1 = null;
					return false;
				}
				catch
				{
					//try-fault
					((IDisposable)this).Dispose();
					throw;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			private void <>m__Finally1()
			{
				<>1__state = -1;
				if (<>7__wrap1 != null)
				{
					<>7__wrap1.Dispose();
				}
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}

			[DebuggerHidden]
			IEnumerator<Type> IEnumerable<Type>.GetEnumerator()
			{
				<WhereNotNull>d__0 <WhereNotNull>d__;
				if (<>1__state == -2 && <>l__initialThreadId == Environment.CurrentManagedThreadId)
				{
					<>1__state = 0;
					<WhereNotNull>d__ = this;
				}
				else
				{
					<WhereNotNull>d__ = new <WhereNotNull>d__0(0);
				}
				<WhereNotNull>d__.types = <>3__types;
				return <WhereNotNull>d__;
			}

			[DebuggerHidden]
			IEnumerator IEnumerable.GetEnumerator()
			{
				return ((IEnumerable<Type>)this).GetEnumerator();
			}
		}

		[IteratorStateMachine(typeof(<WhereNotNull>d__0))]
		internal static IEnumerable<Type> WhereNotNull(this IEnumerable<Type?> types)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WhereNotNull>d__0(-2)
			{
				<>3__types = types
			};
		}
	}
	[Serializable]
	internal sealed class MonsterGuideData
	{
		public SourceInfo source = new SourceInfo();

		public SpawningData spawning = new SpawningData();

		public List<MonsterRecord> monsters = new List<MonsterRecord>();
	}
	[Serializable]
	internal sealed class SourceInfo
	{
		public string name = string.Empty;

		public string url = string.Empty;

		public string license = string.Empty;

		public string lastReviewedUtc = string.Empty;
	}
	[Serializable]
	internal sealed class SpawningData
	{
		public string summary = string.Empty;

		public string level3ReplacementChance = string.Empty;

		public List<SpawningRow> rows = new List<SpawningRow>();

		public List<ReplacementPack> replacementPacks = new List<ReplacementPack>();
	}
	[Serializable]
	internal sealed class SpawningRow
	{
		public string level = string.Empty;

		public int level1Monsters;

		public int level2Monsters;

		public int level3Monsters;
	}
	[Serializable]
	internal sealed class ReplacementPack
	{
		public string monsterId = string.Empty;

		public string name = string.Empty;

		public int count;
	}
	[Serializable]
	internal sealed class MonsterRecord
	{
		public string id = string.Empty;

		public string name = string.Empty;

		public string appearance = string.Empty;

		public string dangerLevel = string.Empty;

		public string health = string.Empty;

		public string damage = string.Empty;

		public string detection = string.Empty;

		public string strengthBreakpoint = string.Empty;

		public string strengthBreakpointStunned = string.Empty;

		public string attacksCrouchedPlayers = string.Empty;

		public string orbSize = string.Empty;

		public string image = string.Empty;
	}
	internal sealed class MonsterDataLoader
	{
		private readonly string _dataPath;

		private readonly string _preferredDataPath;

		private readonly ManualLogSource _logger;

		internal MonsterDataLoader(string pluginDirectory, ManualLogSource logger)
		{
			_dataPath = Path.Combine(pluginDirectory, "Data", "monsters.json");
			_preferredDataPath = _dataPath;
			_logger = logger;
		}

		internal MonsterGuideData Load()
		{
			string text = ResolveDataPath();
			bool flag = File.Exists(text);
			_logger.LogInfo((object)("[MonsterGuide] Data path: " + text));
			_logger.LogInfo((object)$"[MonsterGuide] monsters.json exists: {flag}");
			if (!flag)
			{
				_logger.LogWarning((object)("[MonsterGuide] Monster data file not found: " + text));
				MonsterGuideData monsterGuideData = LoadEmbeddedFallback("Monster data file missing. Embedded defaults loaded.");
				TryWriteEmbeddedDefault(_preferredDataPath);
				LogLoadedCounts(monsterGuideData);
				return monsterGuideData;
			}
			try
			{
				MonsterGuideData monsterGuideData2 = JsonConvert.DeserializeObject<MonsterGuideData>(File.ReadAllText(text));
				if (monsterGuideData2 == null)
				{
					_logger.LogWarning((object)"[MonsterGuide] Monster data JSON loaded as null. Embedded defaults loaded.");
					MonsterGuideData monsterGuideData3 = LoadEmbeddedFallback("Monster data could not be parsed. Embedded defaults loaded.");
					LogLoadedCounts(monsterGuideData3);
					return monsterGuideData3;
				}
				Normalize(monsterGuideData2);
				if (monsterGuideData2.monsters.Count == 0 || monsterGuideData2.spawning.rows.Count == 0)
				{
					_logger.LogWarning((object)"[MonsterGuide] Monster data parsed but contained no monsters or spawn rows. Embedded defaults loaded.");
					MonsterGuideData monsterGuideData4 = LoadEmbeddedFallback("Monster data was empty. Embedded defaults loaded.");
					LogLoadedCounts(monsterGuideData4);
					return monsterGuideData4;
				}
				LogLoadedCounts(monsterGuideData2);
				return monsterGuideData2;
			}
			catch (Exception arg)
			{
				_logger.LogWarning((object)$"[MonsterGuide] Could not parse MonsterGuide data from {text}: {arg}");
				MonsterGuideData monsterGuideData5 = LoadEmbeddedFallback("Monster data is malformed. Embedded defaults loaded. Check BepInEx logs for details.");
				LogLoadedCounts(monsterGuideData5);
				return monsterGuideData5;
			}
		}

		private string ResolveDataPath()
		{
			if (File.Exists(_dataPath))
			{
				return _dataPath;
			}
			string text = Path.Combine(Paths.PluginPath, "MonsterGuide", "Data", "monsters.json");
			if (File.Exists(text))
			{
				return text;
			}
			return _dataPath;
		}

		private static void Normalize(MonsterGuideData data)
		{
			MonsterGuideData monsterGuideData = data;
			if (monsterGuideData.source == null)
			{
				monsterGuideData.source = new SourceInfo();
			}
			monsterGuideData = data;
			if (monsterGuideData.spawning == null)
			{
				monsterGuideData.spawning = new SpawningData();
			}
			SpawningData spawning = data.spawning;
			if (spawning.rows == null)
			{
				spawning.rows = new List<SpawningRow>();
			}
			spawning = data.spawning;
			if (spawning.replacementPacks == null)
			{
				spawning.replacementPacks = new List<ReplacementPack>();
			}
			monsterGuideData = data;
			if (monsterGuideData.monsters == null)
			{
				monsterGuideData.monsters = new List<MonsterRecord>();
			}
			data.monsters.RemoveAll((MonsterRecord monster) => monster == null || string.IsNullOrWhiteSpace(monster.id));
			foreach (MonsterRecord monster in data.monsters)
			{
				monster.name = FirstNonEmpty(monster.name, monster.id);
				monster.image = FirstNonEmpty(monster.image, monster.id + ".png");
			}
		}

		private MonsterGuideData LoadEmbeddedFallback(string message)
		{
			try
			{
				MonsterGuideData monsterGuideData = JsonConvert.DeserializeObject<MonsterGuideData>(ReadEmbeddedDefaultJson());
				if (monsterGuideData != null)
				{
					Normalize(monsterGuideData);
					if (monsterGuideData.monsters.Count > 0 && monsterGuideData.spawning.rows.Count > 0)
					{
						return monsterGuideData;
					}
				}
				_logger.LogWarning((object)"[MonsterGuide] Embedded monsters.json was empty or unreadable.");
			}
			catch (Exception arg)
			{
				_logger.LogWarning((object)$"[MonsterGuide] Could not load embedded monsters.json fallback: {arg}");
			}
			return CreateFallbackData(message);
		}

		private static string ReadEmbeddedDefaultJson()
		{
			using Stream stream = typeof(MonsterDataLoader).Assembly.GetManifestResourceStream("MonsterGuide.Data.monsters.json");
			if (stream == null)
			{
				throw new FileNotFoundException("Embedded resource MonsterGuide.Data.monsters.json was not found.");
			}
			using StreamReader streamReader = new StreamReader(stream, Encoding.UTF8);
			return streamReader.ReadToEnd();
		}

		private void TryWriteEmbeddedDefault(string destinationPath)
		{
			try
			{
				string directoryName = Path.GetDirectoryName(destinationPath);
				if (!string.IsNullOrWhiteSpace(directoryName))
				{
					Directory.CreateDirectory(directoryName);
				}
				File.WriteAllText(destinationPath, ReadEmbeddedDefaultJson(), new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
				_logger.LogInfo((object)("[MonsterGuide] Wrote default monsters.json to " + destinationPath));
			}
			catch (Exception ex)
			{
				_logger.LogWarning((object)("[MonsterGuide] Could not write default monsters.json to " + destinationPath + ": " + ex.Message));
			}
		}

		private void LogLoadedCounts(MonsterGuideData data)
		{
			_logger.LogInfo((object)$"[MonsterGuide] Loaded monsters: {data.monsters.Count}");
			_logger.LogInfo((object)$"[MonsterGuide] Loaded spawn rows: {data.spawning.rows.Count}");
			_logger.LogInfo((object)$"[MonsterGuide] Loaded replacement packs: {data.spawning.replacementPacks.Count}");
		}

		private static MonsterGuideData CreateFallbackData(string message)
		{
			return new MonsterGuideData
			{
				source = new SourceInfo
				{
					name = "Fallback",
					url = string.Empty,
					license = string.Empty,
					lastReviewedUtc = string.Empty
				},
				spawning = new SpawningData
				{
					summary = message,
					level3ReplacementChance = "Unavailable until Data/monsters.json is restored.",
					rows = new List<SpawningRow>
					{
						new SpawningRow
						{
							level = "1-2",
							level1Monsters = 1,
							level2Monsters = 0,
							level3Monsters = 1
						},
						new SpawningRow
						{
							level = "3-5",
							level1Monsters = 1,
							level2Monsters = 1,
							level3Monsters = 1
						},
						new SpawningRow
						{
							level = "6-8",
							level1Monsters = 2,
							level2Monsters = 2,
							level3Monsters = 2
						},
						new SpawningRow
						{
							level = "9",
							level1Monsters = 2,
							level2Monsters = 3,
							level3Monsters = 2
						},
						new SpawningRow
						{
							level = "10-19",
							level1Monsters = 2,
							level2Monsters = 3,
							level3Monsters = 3
						},
						new SpawningRow
						{
							level = "20+",
							level1Monsters = 3,
							level2Monsters = 4,
							level3Monsters = 4
						}
					},
					replacementPacks = new List<ReplacementPack>()
				},
				monsters = new List<MonsterRecord>()
			};
		}

		private static string FirstNonEmpty(string value, string fallback)
		{
			if (!string.IsNullOrWhiteSpace(value))
			{
				return value;
			}
			return fallback;
		}
	}
	internal enum GuideTab
	{
		Spawning,
		Monsters,
		Notes
	}
	internal sealed class MonsterGuideUI
	{
		private const float DefaultWidth = 1120f;

		private const float DefaultHeight = 760f;

		private const float OuterPadding = 14f;

		private const string MonsterSearchControl = "MonsterGuideTextInputMonsterSearch";

		private const string NotesSearchControl = "MonsterGuideTextInputNotesSearch";

		private const string NotesTextControl = "MonsterGuideTextInputNotes";

		private readonly MonsterGuideData _data;

		private readonly NotesManager _notes;

		private readonly ImageLoader _images;

		private readonly ManualLogSource _logger;

		private readonly Action _closeAction;

		private readonly Func<KeyCode> _toggleKey;

		private readonly Dictionary<string, MonsterRecord> _monsterById;

		private Rect _windowRect;

		private GuideTab _tab = GuideTab.Monsters;

		private Vector2 _monsterListScroll;

		private Vector2 _detailScroll;

		private Vector2 _spawningScroll;

		private Vector2 _notesListScroll;

		private Vector2 _notesDetailScroll;

		private string _monsterSearch = string.Empty;

		private string _notesSearch = string.Empty;

		private string _selectedMonsterId = string.Empty;

		private string _editingNotesMonsterId = string.Empty;

		private string _notesText = string.Empty;

		private bool _notesDirty;

		private float _nextNotesSaveTime;

		internal bool TextInputFocused { get; private set; }

		internal MonsterGuideUI(MonsterGuideData data, NotesManager notes, ImageLoader images, ManualLogSource logger, Action closeAction, Func<KeyCode> toggleKey)
		{
			_data = data;
			_notes = notes;
			_images = images;
			_logger = logger;
			_closeAction = closeAction;
			_toggleKey = toggleKey;
			_monsterById = data.monsters.ToDictionary<MonsterRecord, string, MonsterRecord>((MonsterRecord monster) => monster.id, (MonsterRecord monster) => monster, StringComparer.OrdinalIgnoreCase);
			_selectedMonsterId = ((data.monsters.Count > 0) ? data.monsters[0].id : string.Empty);
		}

		internal void OnOpened()
		{
			EnsureWindowRect();
			if (string.IsNullOrWhiteSpace(_selectedMonsterId) && _data.monsters.Count > 0)
			{
				SelectMonster(_data.monsters[0].id);
			}
		}

		internal void Update()
		{
			if (_notesDirty && Time.unscaledTime >= _nextNotesSaveTime)
			{
				FlushNotes();
			}
		}

		internal void Draw()
		{
			//IL_0017: 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_0037: Expected O, but got Unknown
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			MonsterGuideStyles.Ensure();
			EnsureWindowRect();
			DrawBackdrop();
			_windowRect = ClampWindow(GUI.Window(781312, _windowRect, new WindowFunction(DrawWindow), GUIContent.none, MonsterGuideStyles.Window));
			string nameOfFocusedControl = GUI.GetNameOfFocusedControl();
			TextInputFocused = !string.IsNullOrWhiteSpace(nameOfFocusedControl) && nameOfFocusedControl.StartsWith("MonsterGuideTextInput", StringComparison.Ordinal);
		}

		internal void FlushNotes()
		{
			if (_notesDirty)
			{
				if (!string.IsNullOrWhiteSpace(_editingNotesMonsterId))
				{
					_notes.SetNote(_editingNotesMonsterId, _notesText);
					_notes.Save();
				}
				_notesDirty = false;
			}
		}

		private void DrawWindow(int windowId)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			DrawHeader();
			DrawTabs();
			GUILayout.Space(10f);
			switch (_tab)
			{
			case GuideTab.Spawning:
				DrawSpawningTab();
				break;
			case GuideTab.Monsters:
				DrawMonstersTab();
				break;
			case GuideTab.Notes:
				DrawNotesTab();
				break;
			}
			GUILayout.EndVertical();
			GUI.DragWindow(new Rect(0f, 0f, ((Rect)(ref _windowRect)).width, 48f));
		}

		private void DrawHeader()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ec: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = GUILayoutUtility.GetRect(((Rect)(ref _windowRect)).width - 2f, 52f);
			MonsterGuideStyles.DrawRect(rect, new Color(0.04f, 0.07f, 0.08f, 0.98f));
			MonsterGuideStyles.DrawRect(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - 2f, ((Rect)(ref rect)).width, 2f), new Color(0.26f, 0.72f, 0.62f, 1f));
			GUI.Label(new Rect(((Rect)(ref rect)).x + 16f, ((Rect)(ref rect)).y + 8f, 320f, 30f), "MonsterGuide", MonsterGuideStyles.Title);
			GUI.Label(new Rect(((Rect)(ref rect)).x + 17f, ((Rect)(ref rect)).y + 32f, 440f, 18f), BuildHeaderHint(), MonsterGuideStyles.MicroLabel);
			GUI.Label(new Rect(((Rect)(ref rect)).x + 440f, ((Rect)(ref rect)).y + 8f, ((Rect)(ref rect)).width - 570f, 18f), FirstNonEmpty(_data.source.name, "Local monster data"), MonsterGuideStyles.SourceLabel);
			GUI.Label(new Rect(((Rect)(ref rect)).x + 440f, ((Rect)(ref rect)).y + 28f, ((Rect)(ref rect)).width - 570f, 18f), $"Loaded {_data.monsters.Count} monsters | {_data.spawning.rows.Count} spawn rows | {_images.LoadedCount} images", MonsterGuideStyles.SourceLabel);
			if (GUI.Button(new Rect(((Rect)(ref rect)).xMax - 96f, ((Rect)(ref rect)).y + 12f, 78f, 30f), "Close", MonsterGuideStyles.CloseButton))
			{
				_closeAction();
			}
		}

		private string BuildHeaderHint()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			return $"Toggle {_toggleKey()} | Esc closes";
		}

		private void DrawTabs()
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			DrawTabButton(GuideTab.Spawning, "Spawning");
			DrawTabButton(GuideTab.Monsters, "Monsters");
			DrawTabButton(GuideTab.Notes, "Notes / My Notes");
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
		}

		private void DrawTabButton(GuideTab tab, string label)
		{
			GUIStyle val = ((_tab == tab) ? MonsterGuideStyles.TabSelected : MonsterGuideStyles.Tab);
			if (GUILayout.Button(label, val, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width((tab == GuideTab.Notes) ? 190f : 130f),
				GUILayout.Height(34f)
			}) && _tab != tab)
			{
				_tab = tab;
				GUI.FocusControl(string.Empty);
				TextInputFocused = false;
			}
		}

		private void DrawSpawningTab()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			_spawningScroll = GUILayout.BeginScrollView(_spawningScroll, false, true, Array.Empty<GUILayoutOption>());
			GUILayout.BeginVertical(MonsterGuideStyles.Panel, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandHeight(true) });
			GUILayout.Label("Spawning Table", MonsterGuideStyles.SectionTitle, Array.Empty<GUILayoutOption>());
			GUILayout.Label(FirstNonEmpty(_data.spawning.summary, "Monster picks are grouped by danger tier and current map level."), MonsterGuideStyles.BodyLabel, Array.Empty<GUILayoutOption>());
			GUILayout.Space(10f);
			DrawSpawningTable();
			GUILayout.Space(14f);
			GUILayout.Label("Level 3 Replacement Chance", MonsterGuideStyles.SectionTitle, Array.Empty<GUILayoutOption>());
			GUILayout.Label(FirstNonEmpty(_data.spawning.level3ReplacementChance, "No replacement chance data bundled."), MonsterGuideStyles.BodyLabel, Array.Empty<GUILayoutOption>());
			GUILayout.Space(8f);
			DrawReplacementPacks();
			GUILayout.Space(16f);
			if (!string.IsNullOrWhiteSpace(_data.source.url))
			{
				GUILayout.Label("Source: " + _data.source.url, MonsterGuideStyles.MicroLabel, Array.Empty<GUILayoutOption>());
			}
			if (!string.IsNullOrWhiteSpace(_data.source.license))
			{
				GUILayout.Label("Attribution: " + _data.source.license, MonsterGuideStyles.MicroLabel, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndVertical();
			GUILayout.EndScrollView();
		}

		private void DrawSpawningTable()
		{
			GUILayout.BeginVertical(MonsterGuideStyles.Table, Array.Empty<GUILayoutOption>());
			DrawSpawningRow("Level", "Lvl. 1 Monsters", "Lvl. 2 Monsters", "Lvl. 3 Monsters", MonsterGuideStyles.TableHeader);
			foreach (SpawningRow row in _data.spawning.rows)
			{
				DrawSpawningRow(row.level, row.level1Monsters.ToString(), row.level2Monsters.ToString(), row.level3Monsters.ToString(), MonsterGuideStyles.TableCell);
			}
			GUILayout.EndVertical();
		}

		private static void DrawSpawningRow(string level, string levelOne, string levelTwo, string levelThree, GUIStyle style)
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			GUILayout.Label(level, style, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(170f),
				GUILayout.Height(32f)
			});
			GUILayout.Label(levelOne, style, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(190f),
				GUILayout.Height(32f)
			});
			GUILayout.Label(levelTwo, style, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(190f),
				GUILayout.Height(32f)
			});
			GUILayout.Label(levelThree, style, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(190f),
				GUILayout.Height(32f)
			});
			GUILayout.FlexibleSpace();
			GUILayout.EndHorizontal();
		}

		private void DrawReplacementPacks()
		{
			if (_data.spawning.replacementPacks.Count == 0)
			{
				GUILayout.Label("No replacement pack records are bundled.", MonsterGuideStyles.BodyLabel, Array.Empty<GUILayoutOption>());
				return;
			}
			for (int i = 0; i < _data.spawning.replacementPacks.Count; i += 3)
			{
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				for (int j = 0; j < 3 && i + j < _data.spawning.replacementPacks.Count; j++)
				{
					ReplacementPack replacementPack = _data.spawning.replacementPacks[i + j];
					GUILayout.Label($"{replacementPack.count}x {replacementPack.name}", MonsterGuideStyles.Pill, (GUILayoutOption[])(object)new GUILayoutOption[2]
					{
						GUILayout.Width(250f),
						GUILayout.Height(28f)
					});
				}
				GUILayout.EndHorizontal();
				GUILayout.Space(4f);
			}
		}

		private void DrawMonstersTab()
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			DrawMonsterSidebar();
			GUILayout.Space(10f);
			DrawMonsterDetailPanel();
			GUILayout.EndHorizontal();
		}

		private void DrawMonsterSidebar()
		{
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(MonsterGuideStyles.Sidebar, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(292f),
				GUILayout.ExpandHeight(true)
			});
			GUILayout.Label("Monster Index", MonsterGuideStyles.SectionTitle, Array.Empty<GUILayoutOption>());
			GUI.SetNextControlName("MonsterGuideTextInputMonsterSearch");
			_monsterSearch = GUILayout.TextField(_monsterSearch, MonsterGuideStyles.SearchField, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) });
			GUILayout.Space(8f);
			List<MonsterRecord> filteredMonsters = GetFilteredMonsters(_monsterSearch);
			_monsterListScroll = GUILayout.BeginScrollView(_monsterListScroll, false, true, Array.Empty<GUILayoutOption>());
			foreach (MonsterRecord item in filteredMonsters)
			{
				GUIStyle val = (string.Equals(item.id, _selectedMonsterId, StringComparison.OrdinalIgnoreCase) ? MonsterGuideStyles.MonsterButtonSelected : MonsterGuideStyles.MonsterButton);
				if (GUILayout.Button(item.name + "    L" + item.dangerLevel, val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(31f) }))
				{
					SelectMonster(item.id);
				}
			}
			if (filteredMonsters.Count == 0)
			{
				GUILayout.Label("No matching monsters.", MonsterGuideStyles.EmptyLabel, Array.Empty<GUILayoutOption>());
			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
		}

		private List<MonsterRecord> GetFilteredMonsters(string search)
		{
			string search2 = search;
			IEnumerable<MonsterRecord> source = _data.monsters;
			if (!string.IsNullOrWhiteSpace(search2))
			{
				source = source.Where((MonsterRecord monster) => monster.name.IndexOf(search2, StringComparison.OrdinalIgnoreCase) >= 0);
			}
			return source.ToList();
		}

		private void DrawMonsterDetailPanel()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(MonsterGuideStyles.Panel, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.ExpandWidth(true),
				GUILayout.ExpandHeight(true)
			});
			MonsterRecord selectedMonster = GetSelectedMonster();
			if (selectedMonster == null)
			{
				GUILayout.Label("No monster selected.", MonsterGuideStyles.EmptyLabel, Array.Empty<GUILayoutOption>());
				GUILayout.EndVertical();
				return;
			}
			_detailScroll = GUILayout.BeginScrollView(_detailScroll, false, true, Array.Empty<GUILayoutOption>());
			GUILayout.Label(selectedMonster.name, MonsterGuideStyles.MonsterTitle, Array.Empty<GUILayoutOption>());
			DrawMonsterImage(selectedMonster, 180f);
			GUILayout.Space(10f);
			DrawStats(selectedMonster);
			GUILayout.Space(12f);
			DrawNotesEditor(selectedMonster.id, 142f);
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
		}

		private void DrawStats(MonsterRecord monster)
		{
			DrawStatRow("Appearance", monster.appearance);
			DrawStatRow("Danger Level", monster.dangerLevel);
			DrawStatRow("Health", monster.health);
			DrawStatRow("Damage", monster.damage);
			DrawStatRow("Detection", monster.detection);
			DrawStatRow("Strength Breakpoint", monster.strengthBreakpoint);
			DrawStatRow("Strength Breakpoint (Stunned)", monster.strengthBreakpointStunned);
			DrawStatRow("Attacks Crouched Players", monster.attacksCrouchedPlayers);
			DrawStatRow("Orb Size", monster.orbSize);
		}

		private static void DrawStatRow(string label, string value)
		{
			GUILayout.BeginHorizontal(MonsterGuideStyles.StatRow, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinHeight(34f) });
			GUILayout.Label(label, MonsterGuideStyles.StatLabel, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(220f) });
			GUILayout.Label(FirstNonEmpty(value, "Unknown"), MonsterGuideStyles.StatValue, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			GUILayout.EndHorizontal();
			GUILayout.Space(4f);
		}

		private void DrawMonsterImage(MonsterRecord monster, float height)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = GUILayoutUtility.GetRect(1f, height, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			MonsterGuideStyles.DrawRect(rect, new Color(0.03f, 0.045f, 0.05f, 0.96f));
			MonsterGuideStyles.DrawRect(new Rect(((Rect)(ref rect)).x, ((Rect)(ref rect)).yMax - 1f, ((Rect)(ref rect)).width, 1f), new Color(0.24f, 0.48f, 0.44f, 1f));
			Texture2D texture = _images.GetTexture(monster);
			if ((Object)(object)texture == (Object)null)
			{
				GUI.Label(rect, "No image available", MonsterGuideStyles.PlaceholderLabel);
			}
			else
			{
				GUI.DrawTexture(new Rect(((Rect)(ref rect)).x + 8f, ((Rect)(ref rect)).y + 8f, ((Rect)(ref rect)).width - 16f, ((Rect)(ref rect)).height - 16f), (Texture)(object)texture, (ScaleMode)2, true);
			}
		}

		private void DrawNotesTab()
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			DrawNotesSidebar();
			GUILayout.Space(10f);
			DrawNotesDetail();
			GUILayout.EndHorizontal();
		}

		private void DrawNotesSidebar()
		{
			//IL_007f: 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)
			GUILayout.BeginVertical(MonsterGuideStyles.Sidebar, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(292f),
				GUILayout.ExpandHeight(true)
			});
			GUILayout.Label("My Notes", MonsterGuideStyles.SectionTitle, Array.Empty<GUILayoutOption>());
			GUI.SetNextControlName("MonsterGuideTextInputNotesSearch");
			_notesSearch = GUILayout.TextField(_notesSearch, MonsterGuideStyles.SearchField, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(30f) });
			GUILayout.Space(8f);
			List<string> noteMonsterIds = GetNoteMonsterIds();
			_notesListScroll = GUILayout.BeginScrollView(_notesListScroll, false, true, Array.Empty<GUILayoutOption>());
			foreach (string item in noteMonsterIds)
			{
				string displayName = GetDisplayName(item);
				if (string.IsNullOrWhiteSpace(_notesSearch) || displayName.IndexOf(_notesSearch, StringComparison.OrdinalIgnoreCase) >= 0 || item.IndexOf(_notesSearch, StringComparison.OrdinalIgnoreCase) >= 0)
				{
					bool num = string.Equals(item, _selectedMonsterId, StringComparison.OrdinalIgnoreCase);
					bool flag = _notes.HasNote(item);
					GUIStyle val = (num ? MonsterGuideStyles.MonsterButtonSelected : MonsterGuideStyles.MonsterButton);
					if (GUILayout.Button(flag ? (displayName + "  *") : displayName, val, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Height(31f) }))
					{
						SelectMonster(item);
					}
				}
			}
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
		}

		private List<string> GetNoteMonsterIds()
		{
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			foreach (MonsterRecord monster in _data.monsters)
			{
				hashSet.Add(monster.id);
			}
			foreach (string knownMonsterId in _notes.GetKnownMonsterIds())
			{
				hashSet.Add(knownMonsterId);
			}
			List<string> list = hashSet.ToList();
			list.Sort((string left, string right) => string.Compare(GetDisplayName(left), GetDisplayName(right), StringComparison.OrdinalIgnoreCase));
			return list;
		}

		private void DrawNotesDetail()
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			GUILayout.BeginVertical(MonsterGuideStyles.Panel, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.ExpandWidth(true),
				GUILayout.ExpandHeight(true)
			});
			if (string.IsNullOrWhiteSpace(_selectedMonsterId))
			{
				List<string> noteMonsterIds = GetNoteMonsterIds();
				if (noteMonsterIds.Count > 0)
				{
					SelectMonster(noteMonsterIds[0]);
				}
			}
			_notesDetailScroll = GUILayout.BeginScrollView(_notesDetailScroll, false, true, Array.Empty<GUILayoutOption>());
			MonsterRecord selectedMonster = GetSelectedMonster();
			GUILayout.Label(GetDisplayName(_selectedMonsterId), MonsterGuideStyles.MonsterTitle, Array.Empty<GUILayoutOption>());
			if (selectedMonster != null)
			{
				DrawMonsterImage(selectedMonster, 130f);
				GUILayout.Space(8f);
				GUILayout.Label("Danger " + selectedMonster.dangerLevel + "  |  HP " + selectedMonster.health + "  |  Orb " + selectedMonster.orbSize, MonsterGuideStyles.BodyLabel, Array.Empty<GUILayoutOption>());
			}
			else
			{
				GUILayout.Label("This note belongs to a monster id that is not in the current data file. It is kept here so edits to monsters.json do not delete player notes.", MonsterGuideStyles.WarningLabel, Array.Empty<GUILayoutOption>());
			}
			GUILayout.Space(12f);
			DrawNotesEditor(_selectedMonsterId, 330f);
			GUILayout.EndScrollView();
			GUILayout.EndVertical();
		}

		private void DrawNotesEditor(string monsterId, float height)
		{
			if (string.IsNullOrWhiteSpace(monsterId))
			{
				GUILayout.Label("Select a monster to write notes.", MonsterGuideStyles.EmptyLabel, Array.Empty<GUILayoutOption>());
				return;
			}
			BeginEditingNotes(monsterId);
			GUILayout.Label("Player Notes", MonsterGuideStyles.SectionTitle, Array.Empty<GUILayoutOption>());
			GUI.SetNextControlName("MonsterGuideTextInputNotes");
			string text = GUILayout.TextArea(_notesText, MonsterGuideStyles.NotesArea, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.MinHeight(height),
				GUILayout.ExpandWidth(true)
			});
			if (!string.Equals(text, _notesText, StringComparison.Ordinal))
			{
				_notesText = text;
				_notes.SetNote(_editingNotesMonsterId, _notesText);
				_notesDirty = true;
				_nextNotesSaveTime = Time.unscaledTime + 0.6f;
			}
			GUILayout.Label(_notesDirty ? "Autosave pending..." : "Notes saved locally.", MonsterGuideStyles.MicroLabel, Array.Empty<GUILayoutOption>());
		}

		private void SelectMonster(string monsterId)
		{
			//IL_0025: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			if (string.Equals(monsterId, _selectedMonsterId, StringComparison.OrdinalIgnoreCase))
			{
				BeginEditingNotes(monsterId);
				return;
			}
			FlushNotes();
			_selectedMonsterId = monsterId;
			_detailScroll = Vector2.zero;
			_notesDetailScroll = Vector2.zero;
			BeginEditingNotes(monsterId);
		}

		private void BeginEditingNotes(string monsterId)
		{
			if (!string.Equals(monsterId, _editingNotesMonsterId, StringComparison.OrdinalIgnoreCase))
			{
				FlushNotes();
				_editingNotesMonsterId = monsterId;
				_notesText = _notes.GetNote(monsterId);
				_notesDirty = false;
			}
		}

		private MonsterRecord? GetSelectedMonster()
		{
			if (!string.IsNullOrWhiteSpace(_selectedMonsterId) && _monsterById.TryGetValue(_selectedMonsterId, out MonsterRecord value))
			{
				return value;
			}
			return null;
		}

		private string GetDisplayName(string monsterId)
		{
			if (string.IsNullOrWhiteSpace(monsterId))
			{
				return "No monster selected";
			}
			if (!_monsterById.TryGetValue(monsterId, out MonsterRecord value))
			{
				return monsterId + " (missing data)";
			}
			return value.name;
		}

		private void EnsureWindowRect()
		{
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: 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)
			float num = Mathf.Min(1120f, Mathf.Max(360f, (float)Screen.width - 28f));
			float num2 = Mathf.Min(760f, Mathf.Max(320f, (float)Screen.height - 28f));
			if (((Rect)(ref _windowRect)).width <= 0f || ((Rect)(ref _windowRect)).height <= 0f)
			{
				_windowRect = new Rect(((float)Screen.width - num) / 2f, ((float)Screen.height - num2) / 2f, num, num2);
				return;
			}
			((Rect)(ref _windowRect)).width = num;
			((Rect)(ref _windowRect)).height = num2;
			_windowRect = ClampWindow(_windowRect);
		}

		private static Rect ClampWindow(Rect rect)
		{
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			((Rect)(ref rect)).x = Mathf.Clamp(((Rect)(ref rect)).x, 14f, Mathf.Max(14f, (float)Screen.width - ((Rect)(ref rect)).width - 14f));
			((Rect)(ref rect)).y = Mathf.Clamp(((Rect)(ref rect)).y, 14f, Mathf.Max(14f, (float)Screen.height - ((Rect)(ref rect)).height - 14f));
			return rect;
		}

		private static void DrawBackdrop()
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			MonsterGuideStyles.DrawRect(new Rect(0f, 0f, (float)Screen.width, (float)Screen.height), new Color(0f, 0f, 0f, 0.58f));
		}

		private static string FirstNonEmpty(string value, string fallback)
		{
			if (!string.IsNullOrWhiteSpace(value))
			{
				return value;
			}
			return fallback;
		}
	}
	internal static class MonsterGuideStyles
	{
		internal static GUIStyle Window;

		internal static GUIStyle Title;

		internal static GUIStyle SourceLabel;

		internal static GUIStyle MicroLabel;

		internal static GUIStyle SectionTitle;

		internal static GUIStyle BodyLabel;

		internal static GUIStyle WarningLabel;

		internal static GUIStyle EmptyLabel;

		internal static GUIStyle Tab;

		internal static GUIStyle TabSelected;

		internal static GUIStyle CloseButton;

		internal static GUIStyle Sidebar;

		internal static GUIStyle Panel;

		internal static GUIStyle SearchField;

		internal static GUIStyle MonsterButton;

		internal static GUIStyle MonsterButtonSelected;

		internal static GUIStyle MonsterTitle;

		internal static GUIStyle StatRow;

		internal static GUIStyle StatLabel;

		internal static GUIStyle StatValue;

		internal static GUIStyle PlaceholderLabel;

		internal static GUIStyle NotesArea;

		internal static GUIStyle Table;

		internal static GUIStyle TableHeader;

		internal static GUIStyle TableCell;

		internal static GUIStyle Pill;

		private static bool _initialized;

		internal static void Ensure()
		{
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_0029: 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_0057: Expected O, but got Unknown
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: 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_00cc: Expected O, but got Unknown
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Expected O, but got Unknown
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Expected O, but got Unknown
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_019b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Expected O, but got Unknown
			//IL_01d2: 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_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Expected O, but got Unknown
			//IL_0210: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0224: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Expected O, but got Unknown
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0269: Unknown result type (might be due to invalid IL or missing references)
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0282: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Expected O, but got Unknown
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_030c: Expected O, but got Unknown
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_033e: Unknown result type (might be due to invalid IL or missing references)
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0352: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0395: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a9: Expected O, but got Unknown
			//IL_03b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0416: Unknown result type (might be due to invalid IL or missing references)
			//IL_042a: Expected O, but got Unknown
			//IL_0448: Unknown result type (might be due to invalid IL or missing references)
			//IL_045c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0461: Unknown result type (might be due to invalid IL or missing references)
			//IL_046a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0474: Expected O, but got Unknown
			//IL_0474: Unknown result type (might be due to invalid IL or missing references)
			//IL_048e: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a2: Expected O, but got Unknown
			//IL_04ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_04b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c4: Expected O, but got Unknown
			//IL_04c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04de: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f2: Expected O, but got Unknown
			//IL_04fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0501: Unknown result type (might be due to invalid IL or missing references)
			//IL_0509: Unknown result type (might be due to invalid IL or missing references)
			//IL_0510: Unknown result type (might be due to invalid IL or missing references)
			//IL_051a: Expected O, but got Unknown
			//IL_051a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0534: Unknown result type (might be due to invalid IL or missing references)
			//IL_0543: Unknown result type (might be due to invalid IL or missing references)
			//IL_055d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0571: Expected O, but got Unknown
			//IL_058f: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_05c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_05d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_05db: Expected O, but got Unknown
			//IL_05db: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0604: Unknown result type (might be due to invalid IL or missing references)
			//IL_061e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0632: Expected O, but got Unknown
			//IL_0650: Unknown result type (might be due to invalid IL or missing references)
			//IL_0664: Unknown result type (might be due to invalid IL or missing references)
			//IL_0673: Unknown result type (might be due to invalid IL or missing references)
			//IL_0678: Unknown result type (might be due to invalid IL or missing references)
			//IL_0692: Unknown result type (might be due to invalid IL or missing references)
			//IL_06a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_06cf: Expected O, but got Unknown
			//IL_06d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_06f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_06fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0701: Unknown result type (might be due to invalid IL or missing references)
			//IL_070d: Expected O, but got Unknown
			//IL_072b: Unknown result type (might be due to invalid IL or missing references)
			//IL_073f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0744: Unknown result type (might be due to invalid IL or missing references)
			//IL_074b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0755: Expected O, but got Unknown
			//IL_0755: Unknown result type (might be due to invalid IL or missing references)
			//IL_076f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0783: Expected O, but got Unknown
			//IL_078d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0792: Unknown result type (might be due to invalid IL or missing references)
			//IL_079a: Unknown result type (might be due to invalid IL or missing references)
			//IL_07a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ad: Expected O, but got Unknown
			//IL_07cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_07df: Unknown result type (might be due to invalid IL or missing references)
			//IL_07e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_07ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_07f8: Expected O, but got Unknown
			//IL_0816: Unknown result type (might be due to invalid IL or missing references)
			//IL_082a: Unknown result type (might be due to invalid IL or missing references)
			//IL_082f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0837: Unknown result type (might be due to invalid IL or missing references)
			//IL_083e: Unknown result type (might be due to invalid IL or missing references)
			//IL_084a: Expected O, but got Unknown
			//IL_0868: Unknown result type (might be due to invalid IL or missing references)
			//IL_087c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0881: Unknown result type (might be due to invalid IL or missing references)
			//IL_0889: Unknown result type (might be due to invalid IL or missing references)
			//IL_0890: Unknown result type (might be due to invalid IL or missing references)
			//IL_0897: Unknown result type (might be due to invalid IL or missing references)
			//IL_08a1: Expected O, but got Unknown
			//IL_08a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_08bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_08ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_08e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_08f8: Expected O, but got Unknown
			//IL_0916: Unknown result type (might be due to invalid IL or missing references)
			//IL_092a: Unknown result type (might be due to invalid IL or missing references)
			//IL_093e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0943: Unknown result type (might be due to invalid IL or missing references)
			//IL_0948: Unknown result type (might be due to invalid IL or missing references)
			//IL_0952: Expected O, but got Unknown
			//IL_0952: Unknown result type (might be due to invalid IL or missing references)
			//IL_096c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0980: Expected O, but got Unknown
			//IL_098a: Unknown result type (might be due to invalid IL or missing references)
			//IL_098f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0996: Unknown result type (might be due to invalid IL or missing references)
			//IL_099d: Unknown result type (might be due to invalid IL or missing references)
			//IL_09b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_09cb: Expected O, but got Unknown
			//IL_09d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_09e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_09ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_09f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a0f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a23: Expected O, but got Unknown
			//IL_0a41: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a55: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a5a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a61: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a68: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a82: Unknown result type (might be due to invalid IL or missing references)
			//IL_0a96: Expected O, but got Unknown
			//IL_0ab4: Unknown result type (might be due to invalid IL or missing references)
			if (!_initialized)
			{
				GUIStyle val = new GUIStyle(GUI.skin.window)
				{
					padding = new RectOffset(12, 12, 8, 12)
				};
				val.normal.background = MakeTexture(new Color(0.055f, 0.075f, 0.078f, 0.98f));
				Window = val;
				Title = new GUIStyle(GUI.skin.label)
				{
					fontSize = 26,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)3
				};
				Title.normal.textColor = new Color(0.86f, 1f, 0.94f, 1f);
				SourceLabel = new GUIStyle(GUI.skin.label)
				{
					fontSize = 12,
					alignment = (TextAnchor)5
				};
				SourceLabel.normal.textColor = new Color(0.63f, 0.78f, 0.75f, 1f);
				MicroLabel = new GUIStyle(GUI.skin.label)
				{
					fontSize = 11,
					wordWrap = true
				};
				MicroLabel.normal.textColor = new Color(0.6f, 0.7f, 0.68f, 1f);
				SectionTitle = new GUIStyle(GUI.skin.label)
				{
					fontSize = 16,
					fontStyle = (FontStyle)1,
					wordWrap = true
				};
				SectionTitle.normal.textColor = new Color(0.87f, 0.98f, 0.92f, 1f);
				BodyLabel = new GUIStyle(GUI.skin.label)
				{
					fontSize = 13,
					wordWrap = true
				};
				BodyLabel.normal.textColor = new Color(0.84f, 0.89f, 0.86f, 1f);
				WarningLabel = new GUIStyle(BodyLabel)
				{
					fontStyle = (FontStyle)1
				};
				WarningLabel.normal.textColor = new Color(1f, 0.78f, 0.45f, 1f);
				EmptyLabel = new GUIStyle(BodyLabel)
				{
					alignment = (TextAnchor)4,
					fontStyle = (FontStyle)1
				};
				EmptyLabel.normal.textColor = new Color(0.74f, 0.82f, 0.79f, 1f);
				GUIStyle val2 = new GUIStyle(GUI.skin.button)
				{
					fontSize = 13,
					fontStyle = (FontStyle)1,
					margin = new RectOffset(0, 6, 8, 0)
				};
				val2.normal.background = MakeTexture(new Color(0.1f, 0.14f, 0.15f, 1f));
				val2.hover.background = MakeTexture(new Color(0.13f, 0.19f, 0.2f, 1f));
				val2.active.background = MakeTexture(new Color(0.16f, 0.24f, 0.23f, 1f));
				Tab = val2;
				Tab.normal.textColor = new Color(0.7f, 0.84f, 0.8f, 1f);
				Tab.hover.textColor = Color.white;
				GUIStyle val3 = new GUIStyle(Tab);
				val3.normal.background = MakeTexture(new Color(0.18f, 0.39f, 0.34f, 1f));
				val3.hover.background = MakeTexture(new Color(0.2f, 0.46f, 0.4f, 1f));
				TabSelected = val3;
				TabSelected.normal.textColor = Color.white;
				GUIStyle val4 = new GUIStyle(GUI.skin.button)
				{
					fontStyle = (FontStyle)1
				};
				val4.normal.background = MakeTexture(new Color(0.22f, 0.12f, 0.12f, 1f));
				val4.hover.background = MakeTexture(new Color(0.36f, 0.14f, 0.14f, 1f));
				CloseButton = val4;
				CloseButton.normal.textColor = new Color(1f, 0.88f, 0.84f, 1f);
				GUIStyle val5 = new GUIStyle(GUI.skin.box)
				{
					padding = new RectOffset(12, 12, 12, 12)
				};
				val5.normal.background = MakeTexture(new Color(0.075f, 0.095f, 0.105f, 0.96f));
				Sidebar = val5;
				GUIStyle val6 = new GUIStyle(GUI.skin.box)
				{
					padding = new RectOffset(14, 14, 14, 14)
				};
				val6.normal.background = MakeTexture(new Color(0.075f, 0.105f, 0.105f, 0.94f));
				Panel = val6;
				GUIStyle val7 = new GUIStyle(GUI.skin.textField)
				{
					fontSize = 13,
					padding = new RectOffset(9, 9, 6, 6)
				};
				val7.normal.background = MakeTexture(new Color(0.02f, 0.03f, 0.032f, 1f));
				val7.focused.background = MakeTexture(new Color(0.035f, 0.065f, 0.06f, 1f));
				SearchField = val7;
				SearchField.normal.textColor = new Color(0.9f, 1f, 0.96f, 1f);
				SearchField.focused.textColor = Color.white;
				GUIStyle val8 = new GUIStyle(GUI.skin.button)
				{
					alignment = (TextAnchor)3,
					fontSize = 12,
					padding = new RectOffset(10, 8, 4, 4)
				};
				val8.normal.background = MakeTexture(new Color(0.08f, 0.105f, 0.11f, 1f));
				val8.hover.background = MakeTexture(new Color(0.11f, 0.16f, 0.16f, 1f));
				MonsterButton = val8;
				MonsterButton.normal.textColor = new Color(0.82f, 0.9f, 0.86f, 1f);
				MonsterButton.hover.textColor = Color.white;
				GUIStyle val9 = new GUIStyle(MonsterButton);
				val9.normal.background = MakeTexture(new Color(0.19f, 0.39f, 0.34f, 1f));
				val9.hover.background = MakeTexture(new Color(0.22f, 0.46f, 0.4f, 1f));
				MonsterButtonSelected = val9;
				MonsterButtonSelected.normal.textColor = Color.white;
				MonsterTitle = new GUIStyle(GUI.skin.label)
				{
					fontSize = 24,
					fontStyle = (FontStyle)1,
					wordWrap = true
				};
				MonsterTitle.normal.textColor = new Color(0.96f, 1f, 0.91f, 1f);
				GUIStyle val10 = new GUIStyle(GUI.skin.box)
				{
					padding = new RectOffset(10, 10, 7, 7)
				};
				val10.normal.background = MakeTexture(new Color(0.045f, 0.062f, 0.065f, 1f));
				StatRow = val10;
				StatLabel = new GUIStyle(GUI.skin.label)
				{
					fontSize = 12,
					fontStyle = (FontStyle)1,
					wordWrap = true
				};
				StatLabel.normal.textColor = new Color(0.47f, 0.77f, 0.68f, 1f);
				StatValue = new GUIStyle(GUI.skin.label)
				{
					fontSize = 13,
					wordWrap = true
				};
				StatValue.normal.textColor = new Color(0.9f, 0.94f, 0.9f, 1f);
				PlaceholderLabel = new GUIStyle(GUI.skin.label)
				{
					fontSize = 16,
					fontStyle = (FontStyle)1,
					alignment = (TextAnchor)4
				};
				PlaceholderLabel.normal.textColor = new Color(0.52f, 0.64f, 0.61f, 1f);
				GUIStyle val11 = new GUIStyle(GUI.skin.textArea)
				{
					fontSize = 13,
					wordWrap = true,
					padding = new RectOffset(10, 10, 8, 8)
				};
				val11.normal.background = MakeTexture(new Color(0.02f, 0.028f, 0.03f, 1f));
				val11.focused.background = MakeTexture(new Color(0.03f, 0.055f, 0.05f, 1f));
				NotesArea = val11;
				NotesArea.normal.textColor = new Color(0.9f, 0.96f, 0.9f, 1f);
				NotesArea.focused.textColor = Color.white;
				GUIStyle val12 = new GUIStyle(GUI.skin.box)
				{
					padding = new RectOffset(8, 8, 8, 8)
				};
				val12.normal.background = MakeTexture(new Color(0.035f, 0.052f, 0.055f, 1f));
				Table = val12;
				GUIStyle val13 = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)4,
					fontStyle = (FontStyle)1
				};
				val13.normal.background = MakeTexture(new Color(0.17f, 0.32f, 0.3f, 1f));
				TableHeader = val13;
				TableHeader.normal.textColor = Color.white;
				GUIStyle val14 = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)4
				};
				val14.normal.background = MakeTexture(new Color(0.065f, 0.092f, 0.095f, 1f));
				TableCell = val14;
				TableCell.normal.textColor = new Color(0.88f, 0.93f, 0.9f, 1f);
				GUIStyle val15 = new GUIStyle(GUI.skin.label)
				{
					alignment = (TextAnchor)4,
					fontStyle = (FontStyle)1
				};
				val15.normal.background = MakeTexture(new Color(0.09f, 0.16f, 0.17f, 1f));
				Pill = val15;
				Pill.normal.textColor = new Color(0.82f, 0.98f, 0.9f, 1f);
				_initialized = true;
			}
		}

		internal static void DrawRect(Rect rect, Color color)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			Color color2 = GUI.color;
			GUI.color = color;
			GUI.DrawTexture(rect, (Texture)(object)Texture2D.whiteTexture);
			GUI.color = color2;
		}

		private static Texture2D MakeTexture(Color color)
		{
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			Texture2D val = new Texture2D(1, 1, (TextureFormat)4, false)
			{
				hideFlags = (HideFlags)61
			};
			val.SetPixel(0, 0, color);
			val.Apply();
			return val;
		}
	}
	internal sealed class NotesManager
	{
		[Serializable]
		private sealed class NotesFile
		{
			public List<MonsterNoteEntry> notes = new List<MonsterNoteEntry>();
		}

		[Serializable]
		private sealed class MonsterNoteEntry
		{
			public string monsterId = string.Empty;

			public string text = string.Empty;
		}

		private readonly string _notesPath;

		private readonly ManualLogSource _logger;

		private readonly Dictionary<string, string> _notesByMonster = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

		internal string NotesPath => _notesPath;

		internal NotesManager(string notesPath, ManualLogSource logger)
		{
			_notesPath = notesPath;
			_logger = logger;
		}

		internal void Load()
		{
			_notesByMonster.Clear();
			if (!File.Exists(_notesPath))
			{
				return;
			}
			try
			{
				NotesFile notesFile = JsonConvert.DeserializeObject<NotesFile>(File.ReadAllText(_notesPath));
				if (notesFile?.notes == null)
				{
					return;
				}
				foreach (MonsterNoteEntry note in notesFile.notes)
				{
					if (note != null && !string.IsNullOrWhiteSpace(note.monsterId))
					{
						_notesByMonster[note.monsterId] = note.text ?? string.Empty;
					}
				}
				_logger.LogInfo((object)$"Loaded MonsterGuide notes for {_notesByMonster.Count} monsters.");
			}
			catch (Exception ex)
			{
				_logger.LogWarning((object)("Could not load MonsterGuide notes from " + _notesPath + ": " + ex.Message));
			}
		}

		internal string GetNote(string monsterId)
		{
			if (!_notesByMonster.TryGetValue(monsterId, out string value))
			{
				return string.Empty;
			}
			return value;
		}

		internal void SetNote(string monsterId, string text)
		{
			if (!string.IsNullOrWhiteSpace(monsterId))
			{
				if (string.IsNullOrEmpty(text))
				{
					_notesByMonster.Remove(monsterId);
				}
				else
				{
					_notesByMonster[monsterId] = text;
				}
			}
		}

		internal IReadOnlyList<string> GetKnownMonsterIds()
		{
			return _notesByMonster.Keys.OrderBy<string, string>((string id) => id, StringComparer.OrdinalIgnoreCase).ToList();
		}

		internal bool HasNote(string monsterId)
		{
			if (_notesByMonster.TryGetValue(monsterId, out string value))
			{
				return !string.IsNullOrWhiteSpace(value);
			}
			return false;
		}

		internal void Save()
		{
			try
			{
				string directoryName = Path.GetDirectoryName(_notesPath);
				if (!string.IsNullOrWhiteSpace(directoryName))
				{
					Directory.CreateDirectory(directoryName);
				}
				string contents = JsonConvert.SerializeObject((object)new NotesFile
				{
					notes = (from pair in _notesByMonster.OrderBy<KeyValuePair<string, string>, string>((KeyValuePair<string, string> pair) => pair.Key, StringComparer.OrdinalIgnoreCase)
						select new MonsterNoteEntry
						{
							monsterId = pair.Key,
							text = pair.Value
						}).ToList()
				}, (Formatting)1);
				File.WriteAllText(_notesPath, contents, new UTF8Encoding(encoderShouldEmitUTF8Identifier: false));
			}
			catch (Exception ex)
			{
				_logger.LogWarning((object)("Could not save MonsterGuide notes to " + _notesPath + ": " + ex.Message));
			}
		}
	}
	[BepInPlugin("mechgaming13.MonsterGuide", "MonsterGuide", "1.0.0")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "mechgaming13.MonsterGuide";

		public const string PluginName = "MonsterGuide";

		public const string PluginVersion = "1.0.0";

		private ConfigEntry<KeyCode> _toggleKey;

		private ConfigEntry<bool> _resetInputWhileOpen;

		private ConfigEntry<bool> _restoreCursorOnClose;

		private MonsterGuideUI _ui;

		private NotesManager _notes;

		private ImageLoader _images;

		private bool _guideOpen;

		private bool _storedCursorVisible;

		private CursorLockMode _storedCursorLockMode;

		internal static bool GuideOpen { get; private set; }

		private void Awake()
		{
			_toggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyCode>("Controls", "ToggleKey", (KeyCode)286, "Key used to open or close MonsterGuide.");
			_resetInputWhileOpen = ((BaseUnityPlugin)this).Config.Bind<bool>("Input", "ResetInputWhileOpen", true, "Best-effort input quieting while the guide is open.");
			_restoreCursorOnClose = ((BaseUnityPlugin)this).Config.Bind<bool>("Input", "RestoreCursorOnClose", true, "Restore the cursor visibility and lock state that were active before opening the guide.");
			string text = Path.GetDirectoryName(typeof(Plugin).Assembly.Location) ?? Paths.PluginPath;
			MonsterGuideData monsterGuideData = new MonsterDataLoader(text, ((BaseUnityPlugin)this).Logger).Load();
			_notes = new NotesManager(Path.Combine(Paths.ConfigPath, "MonsterGuide", "notes.json"), ((BaseUnityPlugin)this).Logger);
			_notes.Load();
			_images = new ImageLoader(Path.Combine(text, "Images"), ((BaseUnityPlugin)this).Logger);
			_images.Preload(monsterGuideData.monsters);
			_ui = new MonsterGuideUI(monsterGuideData, _notes, _images, ((BaseUnityPlugin)this).Logger, delegate
			{
				SetGuideOpen(open: false);
			}, () => _toggleKey.Value);
			InputBlocker.Init(((BaseUnityPlugin)this).Logger);
			InputBlocker.PatchAvailableHotkeyReaders();
			((BaseUnityPlugin)this).Logger.LogInfo((object)("MonsterGuide 1.0.0 loaded. Data path: " + Path.Combine(text, "Data", "monsters.json")));
		}

		private void Update()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (_guideOpen)
			{
				InputBlocker.PatchAvailableHotkeyReaders();
				if (HotkeyInput.GetKeyDown(_toggleKey.Value) || HotkeyInput.GetKeyDown((KeyCode)27))
				{
					SetGuideOpen(open: false);
					return;
				}
				_ui.Update();
				ResetInputIfConfigured();
			}
			else if (HotkeyInput.GetKeyDown(_toggleKey.Value) && HotkeyInput.NoTextInputActive())
			{
				SetGuideOpen(open: true);
			}
		}

		private void LateUpdate()
		{
			if (_guideOpen)
			{
				Cursor.visible = true;
				Cursor.lockState = (CursorLockMode)0;
			}
		}

		private void OnGUI()
		{
			if (_guideOpen)
			{
				_ui.Draw();
				ConsumeKeyboardEvent();
			}
		}

		private void OnDestroy()
		{
			SetGuideOpen(open: false);
			_ui?.FlushNotes();
			_images?.DestroyAll();
			InputBlocker.Unpatch();
			GuideOpen = false;
		}

		private void SetGuideOpen(bool open)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			if (_guideOpen == open)
			{
				return;
			}
			_guideOpen = open;
			GuideOpen = open;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("MonsterGuide " + (open ? "opened" : "closed") + "."));
			if (open)
			{
				InputBlocker.PatchAvailableHotkeyReaders();
				_storedCursorVisible = Cursor.visible;
				_storedCursorLockMode = Cursor.lockState;
				Cursor.visible = true;
				Cursor.lockState = (CursorLockMode)0;
				_ui.OnOpened();
			}
			else
			{
				_ui.FlushNotes();
				if (_restoreCursorOnClose.Value)
				{
					Cursor.visible = _storedCursorVisible;
					Cursor.lockState = _storedCursorLockMode;
				}
			}
		}

		private static void ConsumeKeyboardEvent()
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Invalid comparison between Unknown and I4
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Invalid comparison between Unknown and I4
			Event current = Event.current;
			if (current != null && ((int)current.type == 4 || (int)current.type == 5))
			{
				current.Use();
			}
		}

		private void ResetInputIfConfigured()
		{
			if (!_resetInputWhileOpen.Value)
			{
				return;
			}
			try
			{
				Input.ResetInputAxes();
			}
			catch
			{
			}
		}
	}
}