Decompiled source of VisualItemSpawner v1.0.1

plugins/VisualItemSpawner/VisualItemSpawner.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.UI;
using VisualItemSpawner.Catalog;
using VisualItemSpawner.Images;
using VisualItemSpawner.Multiplayer;
using VisualItemSpawner.Patches;
using VisualItemSpawner.Spawning;
using VisualItemSpawner.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyCompany("Poedil")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright (c) 2026 Poedil")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("VisualItemSpawner")]
[assembly: AssemblyTitle("VisualItemSpawner")]
[assembly: AssemblyVersion("1.0.1.0")]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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]
	[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;
		}
	}
}
namespace VisualItemSpawner
{
	public static class LegacyFileMigration
	{
		public static bool CopySingle(string directory, string legacyPattern, string destination, bool replaceEmptyConfig = false)
		{
			string[] array;
			if (File.Exists(destination))
			{
				if (!replaceEmptyConfig)
				{
					return false;
				}
				array = File.ReadAllLines(destination);
				for (int i = 0; i < array.Length; i++)
				{
					string text = array[i].Trim();
					if (text.Length > 0 && !text.StartsWith("#", StringComparison.Ordinal) && !text.StartsWith(";", StringComparison.Ordinal) && text.IndexOf('=') >= 0)
					{
						return false;
					}
				}
			}
			string text2 = null;
			array = Directory.GetFiles(directory, legacyPattern);
			foreach (string text3 in array)
			{
				if (!string.Equals(Path.GetFullPath(text3), Path.GetFullPath(destination), StringComparison.OrdinalIgnoreCase))
				{
					if (text2 != null)
					{
						return false;
					}
					text2 = text3;
				}
			}
			if (text2 == null)
			{
				return false;
			}
			File.Copy(text2, destination, replaceEmptyConfig);
			return true;
		}
	}
	[BepInPlugin("visualitemspawner", "Visual Item Spawner", "1.0.1")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "visualitemspawner";

		public const string PluginVersion = "1.0.1";

		private const string ConfigSection = "VisualItemSpawner";

		private GameItemCatalog? m_catalog;

		private GameItemImageProvider? m_images;

		private LocalSpawnService? m_spawnService;

		private CreatureCatalog? m_creatureCatalog;

		private CreatureSpawnService? m_creatureSpawnService;

		private CreatureImageProvider? m_creatureImages;

		private VisNetwork? m_network;

		private ItemBrowser? m_browser;

		private CreatureBrowser? m_creatureBrowser;

		private Harmony? m_harmony;

		private FavoritesStore? m_favorites;

		private bool m_favoritesMigrated;

		private KeyCode m_toggleKey = (KeyCode)287;

		private KeyCode m_creatureToggleKey = (KeyCode)288;

		private bool m_patched;

		private bool m_running;

		private double m_lastCatalogCheck;

		private int m_maxQuantity = 100;

		private bool m_allowInventory = true;

		private bool m_allowGround = true;

		private bool m_markAsCheated;

		private bool m_allowNonAdminItems;

		private int m_nonAdminMaxQuantity = 20;

		private string m_excludedIngredientNames = "";

		private bool m_creaturesTamedByDefault;

		private string m_excludedCreatureNames = "";

		private string m_includedItemPrefabs = "";

		private string m_excludedItemPrefabs = "";

		private int m_maxCreatureLevel = 10;

		private int m_maxCreaturesInArea = 20;

		private bool m_allowNonAdminCreatures;

		private int m_nonAdminMaxCreatureLevel = 1;

		private int m_requestsPerWindow = 20;

		private float m_rateWindowSeconds = 5f;

		private float m_helloRetrySeconds = 2f;

		private float m_helloTimeoutSeconds = 15f;

		private void Awake()
		{
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0187: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_0198: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c0: Expected O, but got Unknown
			//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e0: Unknown result type (might be due to invalid IL or missing references)
			MigrateLegacyFiles();
			bool num = BindSetting("01 - General", "Enabled", fallback: true, "Enable this mod. Restart required.");
			string name = BindSetting("02 - Browser", "ToggleKey", "F6", "Client item browser hotkey. Restart required.");
			string name2 = BindSetting("02 - Browser", "CreatureToggleKey", "F7", "Client creature browser hotkey. Restart required.");
			int num2 = BindSetting("04 - Server spawning", "MaxQuantityPerRequest", 100, "Server maximum quantity per request, 1 to 1000.");
			bool allowInventory = BindSetting("04 - Server spawning", "AllowInventory", fallback: true, "Allow giving inventory items. Server authoritative.");
			bool allowGround = BindSetting("04 - Server spawning", "AllowGround", fallback: true, "Allow ground item drops. Server authoritative.");
			bool markAsCheated = BindSetting("04 - Server spawning", "MarkItemsAsCheated", fallback: false, "Mark delivered items as cheated. Set consistently on client and server.");
			bool allowNonAdminItems = BindSetting("05 - Server permissions", "AllowNonAdminItems", fallback: false, "Allow non-admin players to spawn items. Default false.");
			int num3 = BindSetting("05 - Server permissions", "NonAdminMaxQuantityPerRequest", 20, "Non-admin quantity ceiling. Cannot exceed server maximum.");
			string excludedIngredientNames = BindSetting("02 - Browser", "ExcludedIngredientNames", "idol", "Client comma-separated ingredient name exclusions.");
			bool creaturesTamedByDefault = BindSetting("02 - Browser", "CreaturesTamedByDefault", fallback: false, "Client default for the tamed toggle.");
			string excludedCreatureNames = BindSetting("03 - Catalog", "ExcludedCreatureNames", "", "Comma-separated creature exclusions. Use matching client/server values.");
			int num4 = BindSetting("04 - Server spawning", "MaxCreatureLevel", 10, "Server creature level ceiling, 1 to 50.");
			bool allowNonAdminCreatures = BindSetting("05 - Server permissions", "AllowNonAdminCreatures", fallback: false, "Allow non-admin players to spawn creatures. Default false.");
			int num5 = BindSetting("05 - Server permissions", "NonAdminMaxCreatureLevel", 1, "Non-admin level ceiling. Cannot exceed server maximum.");
			m_toggleKey = ParseKey(name, (KeyCode)287);
			m_creatureToggleKey = ParseKey(name2, (KeyCode)288);
			if (!num)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Visual Item Spawner is disabled in the configuration.");
				return;
			}
			m_harmony = new Harmony("visualitemspawner");
			int num6 = BrowserPatches.Apply(m_harmony, (Action<string>)((BaseUnityPlugin)this).Logger.LogInfo, (Action<string>)((BaseUnityPlugin)this).Logger.LogError);
			m_patched = num6 > 0;
			m_maxQuantity = Mathf.Clamp(num2, 1, 1000);
			m_allowInventory = allowInventory;
			m_allowGround = allowGround;
			m_markAsCheated = markAsCheated;
			m_allowNonAdminItems = allowNonAdminItems;
			m_nonAdminMaxQuantity = Mathf.Clamp(num3, 1, m_maxQuantity);
			m_excludedIngredientNames = excludedIngredientNames;
			m_creaturesTamedByDefault = creaturesTamedByDefault;
			m_excludedCreatureNames = excludedCreatureNames;
			m_includedItemPrefabs = BindSetting("03 - Catalog", "IncludedItemPrefabs", "", "Exact comma-separated prefab IDs that bypass NPC equipment exclusions. Does not bypass internal-data filtering or spawn permissions. Match client/server values.");
			m_excludedItemPrefabs = BindSetting("03 - Catalog", "ExcludedItemPrefabs", "", "Exact comma-separated prefab IDs to exclude. Takes precedence over included IDs. Match client/server values.");
			m_maxCreatureLevel = Mathf.Clamp(num4, 1, 50);
			m_maxCreaturesInArea = Math.Max(0, BindSetting("04 - Server spawning", "MaxCreaturesInArea", 20, "Maximum living non-player creatures within 50 metres of each spawn position, including the full batch. Counts wild, tamed, summoned, NPCs and bosses. Applies to admins too. 0 disables. Server authoritative."));
			m_allowNonAdminCreatures = allowNonAdminCreatures;
			m_nonAdminMaxCreatureLevel = Mathf.Clamp(num5, 1, m_maxCreatureLevel);
			m_requestsPerWindow = Mathf.Clamp(BindSetting("06 - Network", "RequestsPerWindow", 20, "Server requests allowed per player per rate-limit window, 1 to 200."), 1, 200);
			m_rateWindowSeconds = Mathf.Clamp(BindSetting("06 - Network", "RateWindowSeconds", 5f, "Server rate-limit window in seconds, 1 to 60."), 1f, 60f);
			m_helloRetrySeconds = Mathf.Clamp(BindSetting("06 - Network", "HandshakeRetrySeconds", 2f, "Client handshake retry interval in seconds, 1 to 10."), 1f, 10f);
			m_helloTimeoutSeconds = Mathf.Clamp(BindSetting("06 - Network", "HandshakeTimeoutSeconds", 15f, "Client time before showing missing-server-support warning, 5 to 120 seconds. Retries continue."), 5f, 120f);
			((BaseUnityPlugin)this).Config.Save();
			m_running = true;
			((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format("Visual Item Spawner {0} loaded (protocol {1}). Toggle key: {2}. Creature key: {3}.", "1.0.1", 5, m_toggleKey, m_creatureToggleKey));
		}

		private T BindSetting<T>(string section, string key, T fallback, string description)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>("VisualItemSpawner", key, fallback, (ConfigDescription)null);
			ConfigEntry<T> obj = ((BaseUnityPlugin)this).Config.Bind<T>(section, key, val.Value, description + " Restart required.");
			((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("VisualItemSpawner", key));
			return obj.Value;
		}

		private void OnEnable()
		{
			Localization.OnLanguageChange = (Action)Delegate.Combine(Localization.OnLanguageChange, new Action(OnLanguageChange));
		}

		private void OnDisable()
		{
			Localization.OnLanguageChange = (Action)Delegate.Remove(Localization.OnLanguageChange, new Action(OnLanguageChange));
			Teardown();
		}

		private void Update()
		{
			//IL_0108: 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)
			if (!m_running)
			{
				return;
			}
			try
			{
				EnsureServices();
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Service setup failed: {arg}");
				m_running = false;
				return;
			}
			if (m_network != null)
			{
				try
				{
					m_network.Tick();
				}
				catch (Exception arg2)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)$"Network tick failed: {arg2}");
				}
			}
			MaybeRebuildCatalog();
			if (m_browser == null)
			{
				return;
			}
			if (ZInput.GetKeyDown(m_toggleKey, true))
			{
				if (m_browser.IsOpen)
				{
					CloseBrowser();
				}
				else
				{
					if (m_creatureBrowser != null && m_creatureBrowser.IsOpen)
					{
						CloseCreatureBrowser();
					}
					m_browser.Open();
					if (m_browser.IsOpen)
					{
						InputBlock.Set(value: true);
					}
				}
			}
			if (m_browser.IsOpen)
			{
				try
				{
					m_browser.Update();
				}
				catch (Exception arg3)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)$"Browser update failed: {arg3}");
					CloseBrowser();
				}
			}
			if (ZInput.GetKeyDown(m_creatureToggleKey, true))
			{
				if (m_creatureBrowser != null && m_creatureBrowser.IsOpen)
				{
					CloseCreatureBrowser();
				}
				else
				{
					if (m_browser.IsOpen)
					{
						CloseBrowser();
					}
					OpenCreatureBrowser();
				}
			}
			if (m_creatureBrowser == null || !m_creatureBrowser.IsOpen)
			{
				return;
			}
			try
			{
				m_creatureBrowser.Update();
			}
			catch (Exception arg4)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"Creature browser update failed: {arg4}");
				CloseCreatureBrowser();
			}
		}

		private void OnDestroy()
		{
			Teardown();
			if (m_patched && m_harmony != null)
			{
				m_harmony.UnpatchSelf();
				m_patched = false;
			}
			m_harmony = null;
		}

		private void CloseBrowser()
		{
			m_browser?.Close();
			InputBlock.Set(value: false);
		}

		private void OpenCreatureBrowser()
		{
			if (m_creatureBrowser != null)
			{
				m_creatureBrowser.Open();
				if (m_creatureBrowser.IsOpen)
				{
					InputBlock.Set(value: true);
				}
			}
		}

		private void CloseCreatureBrowser()
		{
			m_creatureBrowser?.Close();
			InputBlock.Set(value: false);
		}

		private void EnsureServices()
		{
			if ((Object)(object)ObjectDB.instance == (Object)null)
			{
				if (m_spawnService != null || m_browser != null)
				{
					Teardown();
				}
				return;
			}
			if (m_spawnService == null)
			{
				CreateServices();
			}
			if (m_favorites == null)
			{
				m_favorites = LoadFavorites();
			}
			if (!m_favoritesMigrated && m_favorites != null && m_catalog != null && m_catalog.GetItems().Count > 0)
			{
				m_favoritesMigrated = true;
				bool flag = false;
				foreach (ItemEntry item in m_catalog.GetItems())
				{
					string text = m_catalog.GetSharedData(item.PrefabId)?.m_name;
					if (!string.IsNullOrEmpty(text) && m_favorites.IsItemFavorite(text))
					{
						m_favorites.SetItemFavorite(item.PrefabId, favorite: true);
						flag = true;
					}
				}
				if (flag)
				{
					foreach (ItemEntry item2 in m_catalog.GetItems())
					{
						string text2 = m_catalog.GetSharedData(item2.PrefabId)?.m_name;
						if (!string.IsNullOrEmpty(text2) && text2 != item2.PrefabId)
						{
							m_favorites.SetItemFavorite(text2, favorite: false);
						}
					}
					SaveFavorites();
				}
			}
			bool flag2 = (Object)(object)Player.m_localPlayer != (Object)null;
			if (flag2 && m_browser == null)
			{
				m_images = new GameItemImageProvider();
				ItemBrowser itemBrowser = new ItemBrowser(m_catalog, m_images, Spawn, CanSpawnItems);
				VisNetwork? network = m_network;
				itemBrowser.MaxQuantityPerRequest = ((network != null && network.ServerMaxQuantity > 0) ? m_network.ServerMaxQuantity : m_spawnService.MaxQuantityPerRequest);
				m_browser = itemBrowser;
				m_browser.UnavailableReason = () => m_network?.ItemUnavailableReason ?? "Network services unavailable.";
				m_browser.Favorites = m_favorites;
				m_browser.FavoritesChanged += SaveFavorites;
				m_browser.ExcludedIngredients = m_excludedIngredientNames.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries);
				m_browser.Closed += OnBrowserClosed;
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Browser ready with {m_catalog.GetItems().Count} items.");
				((BaseUnityPlugin)this).Logger.LogInfo((object)m_images.Diagnose(m_catalog.GetItems()));
			}
			else if (!flag2 && m_browser != null)
			{
				ReleaseBrowser();
			}
			if (flag2 && m_creatureBrowser == null)
			{
				m_creatureImages = new CreatureImageProvider(m_creatureCatalog);
				CreatureBrowser creatureBrowser = new CreatureBrowser(m_creatureCatalog, SpawnCreature, CanSpawnCreatures, Spawn, CanSpawnItems);
				VisNetwork? network2 = m_network;
				creatureBrowser.MaxQuantityPerRequest = ((network2 != null && network2.ServerMaxQuantity > 0) ? m_network.ServerMaxQuantity : m_creatureSpawnService.MaxQuantityPerRequest);
				creatureBrowser.TamedByDefault = m_creaturesTamedByDefault;
				VisNetwork? network3 = m_network;
				creatureBrowser.MaxCreatureLevel = ((network3 != null && network3.ServerMaxCreatureLevel > 0) ? m_network.ServerMaxCreatureLevel : m_maxCreatureLevel);
				m_creatureBrowser = creatureBrowser;
				m_creatureBrowser.UnavailableReason = () => m_network?.CreatureUnavailableReason ?? "Network services unavailable.";
				m_creatureBrowser.Images = m_creatureImages;
				m_creatureBrowser.Favorites = m_favorites;
				m_creatureBrowser.FavoritesChanged += SaveFavorites;
				m_creatureBrowser.Closed += OnBrowserClosed;
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Creature browser ready with {m_creatureCatalog.GetItems().Count} creatures.");
			}
			else if (!flag2 && m_creatureBrowser != null)
			{
				ReleaseCreatureBrowser();
			}
		}

		private void ReleaseBrowser()
		{
			if (m_browser != null)
			{
				m_browser.Closed -= OnBrowserClosed;
				m_browser.FavoritesChanged -= SaveFavorites;
				m_browser.Dispose();
				m_browser = null;
				m_images?.Clear();
				m_images = null;
				InputBlock.Set(value: false);
			}
		}

		private void ReleaseCreatureBrowser()
		{
			if (m_creatureBrowser != null)
			{
				m_creatureBrowser.Closed -= OnBrowserClosed;
				m_creatureBrowser.FavoritesChanged -= SaveFavorites;
				m_creatureBrowser.Dispose();
				m_creatureBrowser = null;
				InputBlock.Set(value: false);
			}
		}

		private void ReleaseCreatureImages()
		{
			if (m_creatureImages != null)
			{
				m_creatureImages.Dispose();
				m_creatureImages = null;
			}
		}

		private void OnBrowserClosed()
		{
			InputBlock.Set(value: false);
		}

		private void MigrateLegacyFiles()
		{
			try
			{
				if (((BaseUnityPlugin)this).Config.Count == 0 && LegacyFileMigration.CopySingle(Paths.ConfigPath, "*.visualitemspawner.cfg", ((BaseUnityPlugin)this).Config.ConfigFilePath, replaceEmptyConfig: true))
				{
					((BaseUnityPlugin)this).Config.Reload();
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Existing configuration migrated to the new mod identifier.");
				}
				if (LegacyFileMigration.CopySingle(Paths.ConfigPath, "*.visualitemspawner.favorites.json", FavoritesPath()))
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Existing favorites migrated to the new mod identifier.");
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Legacy file migration failed: " + ex.Message));
			}
		}

		private static string FavoritesPath()
		{
			return Path.Combine(Paths.ConfigPath, "visualitemspawner.favorites.json");
		}

		private FavoritesStore LoadFavorites()
		{
			try
			{
				string path = FavoritesPath();
				if (File.Exists(path))
				{
					return FavoritesStore.FromJson(File.ReadAllText(path));
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Favorites could not be loaded, starting empty: " + ex.Message));
			}
			return new FavoritesStore();
		}

		private void SaveFavorites()
		{
			try
			{
				if (m_favorites != null)
				{
					File.WriteAllText(FavoritesPath(), m_favorites.ToJson());
				}
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Favorites could not be saved: " + ex.Message));
			}
		}

		private void CreateServices()
		{
			m_catalog = new GameItemCatalog
			{
				IncludedItemPrefabs = m_includedItemPrefabs,
				ExcludedItemPrefabs = m_excludedItemPrefabs
			};
			m_catalog.Rebuild();
			LogNpcExclusions();
			m_creatureCatalog = new CreatureCatalog();
			m_creatureCatalog.SetExcludedNameParts(m_excludedCreatureNames.Split(new char[1] { ',' }, StringSplitOptions.RemoveEmptyEntries));
			m_creatureCatalog.Rebuild();
			m_spawnService = new LocalSpawnService(m_catalog)
			{
				MaxQuantityPerRequest = m_maxQuantity,
				AllowInventory = m_allowInventory,
				AllowGround = m_allowGround,
				MarkItemsAsCheated = m_markAsCheated
			};
			m_creatureSpawnService = new CreatureSpawnService(m_creatureCatalog)
			{
				MaxQuantityPerRequest = m_maxQuantity,
				MaxCreatureLevel = m_maxCreatureLevel,
				MaxCreaturesInArea = m_maxCreaturesInArea
			};
			m_network = new VisNetwork(m_spawnService, m_creatureSpawnService, m_requestsPerWindow, m_rateWindowSeconds)
			{
				ModVersion = "1.0.1",
				HandshakeRetrySeconds = m_helloRetrySeconds,
				HandshakeTimeoutSeconds = m_helloTimeoutSeconds,
				LogInfo = delegate(string message)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)message);
				},
				LogWarning = delegate(string message)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)message);
				}
			};
			m_network.AccessPolicy.AllowNonAdminItems = m_allowNonAdminItems;
			m_network.AccessPolicy.NonAdminMaxQuantityPerRequest = m_nonAdminMaxQuantity;
			m_network.AccessPolicy.AllowNonAdminCreatures = m_allowNonAdminCreatures;
			m_network.AccessPolicy.NonAdminMaxCreatureLevel = m_nonAdminMaxCreatureLevel;
			m_network.OnOutcome += OnSpawnOutcome;
			m_network.OnWelcome += ApplyServerLimits;
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"Item database ready with {m_catalog.GetItems().Count} items ({m_catalog.LastUnlistedCount} engine data and furniture entries not listed, {m_catalog.LastExcludedCount} NPC/configured items and build pieces excluded, {m_catalog.LastDuplicateCount} duplicate names disambiguated).");
			((BaseUnityPlugin)this).Logger.LogInfo((object)("prefab components: " + m_catalog.LastSignalSummary));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("internal entries recognised and not listed: " + m_catalog.DescribeInternals(40)));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("duplicate names shown with their id: " + m_catalog.DescribeHiddenDuplicates()));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("armor sets: " + m_catalog.DescribeSets(12)));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("prefabs not named after their item: " + m_catalog.DescribeNameMismatches()));
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"creature database ready with {m_creatureCatalog.GetItems().Count} creatures ({m_creatureCatalog.LastDisabledCount} disabled in the scene, {m_creatureCatalog.LastExcludedCount} excluded by name, {m_creatureCatalog.UntameableCount} untameable).");
			((BaseUnityPlugin)this).Logger.LogInfo((object)("creature name exclusions: " + m_creatureCatalog.DescribeExclusions()));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("spirit group members: " + m_creatureCatalog.DescribeSpirit()));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("creature categories: " + m_creatureCatalog.DescribeCategories()));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("creature factions: " + m_creatureCatalog.DescribeFactions()));
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"creature level range: 1 to {m_maxCreatureLevel}.");
			((BaseUnityPlugin)this).Logger.LogInfo((object)("non-admin item access: " + (m_allowNonAdminItems ? $"allowed up to {m_nonAdminMaxQuantity} per request" : "denied") + "."));
			((BaseUnityPlugin)this).Logger.LogInfo((object)("non-admin creature access: " + (m_allowNonAdminCreatures ? $"allowed up to level {m_nonAdminMaxCreatureLevel}" : "denied") + "."));
			if (m_creatureCatalog.DuplicateIdCount > 0)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)$"[VisualItemSpawner] {m_creatureCatalog.DuplicateIdCount} prefab names are used by more than one creature, so they share a picture and a spawn target: {m_creatureCatalog.DescribeDuplicateIds(40)}");
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)("untameable creatures: " + m_creatureCatalog.DescribeUntameable(40)));
		}

		private void Teardown()
		{
			CloseBrowser();
			ReleaseBrowser();
			CloseCreatureBrowser();
			ReleaseCreatureBrowser();
			ReleaseCreatureImages();
			if (m_network != null)
			{
				m_network.OnOutcome -= OnSpawnOutcome;
				m_network.OnWelcome -= ApplyServerLimits;
				m_network.Shutdown();
				m_network = null;
			}
			m_spawnService = null;
			m_creatureSpawnService = null;
			m_catalog = null;
			m_creatureCatalog = null;
		}

		private void LogNpcExclusions()
		{
			if (m_catalog == null)
			{
				return;
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)$"NPC/configured item exclusions: {m_catalog.LastNpcExclusions.Count}.");
			foreach (string lastNpcExclusion in m_catalog.LastNpcExclusions)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Item excluded: " + lastNpcExclusion));
			}
		}

		private void MaybeRebuildCatalog()
		{
			bool flag = m_catalog != null && !m_catalog.IsUpToDate();
			bool flag2 = m_creatureCatalog != null && !m_creatureCatalog.IsUpToDate();
			bool flag3 = m_catalog != null;
			if (!flag && !flag2 && !flag3)
			{
				return;
			}
			double realtimeSinceStartupAsDouble = Time.realtimeSinceStartupAsDouble;
			if (!(realtimeSinceStartupAsDouble - m_lastCatalogCheck < 5.0))
			{
				m_lastCatalogCheck = realtimeSinceStartupAsDouble;
				if (flag && m_catalog != null)
				{
					m_catalog.Rebuild();
					LogNpcExclusions();
					m_images?.Clear();
					m_browser?.Invalidate();
					((BaseUnityPlugin)this).Logger.LogInfo((object)"Item catalog rebuilt after an item database change.");
				}
				if (m_catalog != null && m_catalog.RefreshRecipesIfStale())
				{
					m_browser?.Invalidate();
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"Recipe index rebuilt with {m_catalog.RecipeCount} recipes.");
				}
				if (flag2)
				{
					int num = m_creatureCatalog.Rebuild();
					m_creatureImages?.Clear();
					m_creatureBrowser?.Invalidate();
					((BaseUnityPlugin)this).Logger.LogInfo((object)$"Creature catalog rebuilt with {num} creatures. Categories: {m_creatureCatalog.DescribeCategories()}");
					((BaseUnityPlugin)this).Logger.LogInfo((object)("spirit group: " + m_creatureCatalog.DescribeSpirit()));
					((BaseUnityPlugin)this).Logger.LogInfo((object)("creature factions: " + m_creatureCatalog.DescribeFactions()));
				}
			}
		}

		private void OnLanguageChange()
		{
			m_catalog?.Rebuild();
			m_images?.Clear();
			m_browser?.Invalidate();
			m_creatureCatalog?.Rebuild();
			m_creatureImages?.Clear();
			m_creatureBrowser?.Invalidate();
		}

		private void OnSpawnOutcome(SpawnOutcome outcome)
		{
			((BaseUnityPlugin)this).Logger.LogInfo((object)(string.Format("spawn {0} x{1} ", outcome.Request?.PrefabId ?? "?", outcome.Request?.Quantity ?? 0) + "-> " + (outcome.Request?.Destination.ToString() ?? "?") + ": " + $"{outcome.Result.Status} delivered {outcome.Result.DeliveredQuantity} ({outcome.Result.Message})"));
			if (outcome.Request != null && outcome.Request.Kind == SpawnKind.Creature)
			{
				m_creatureBrowser?.ShowOutcome(outcome);
			}
			else
			{
				m_browser?.ShowOutcome(outcome);
			}
		}

		private bool CanSpawnItems()
		{
			if (m_network == null)
			{
				return false;
			}
			if (!m_network.IsClientSession)
			{
				return true;
			}
			return m_network.ServerAllowsItems;
		}

		private bool CanSpawnCreatures()
		{
			if (m_network == null)
			{
				return false;
			}
			if (!m_network.IsClientSession)
			{
				return true;
			}
			return m_network.ServerAllowsCreatures;
		}

		private void ApplyServerLimits(bool _)
		{
			if (m_network == null)
			{
				return;
			}
			if (m_browser != null && m_network.ServerMaxQuantity > 0)
			{
				m_browser.MaxQuantityPerRequest = m_network.ServerMaxQuantity;
				m_browser.Invalidate();
			}
			if (m_creatureBrowser != null)
			{
				if (m_network.ServerMaxQuantity > 0)
				{
					m_creatureBrowser.MaxQuantityPerRequest = m_network.ServerMaxQuantity;
				}
				if (m_network.ServerMaxCreatureLevel > 0)
				{
					m_creatureBrowser.MaxCreatureLevel = m_network.ServerMaxCreatureLevel;
				}
				m_creatureBrowser.Invalidate();
			}
		}

		private bool Spawn(SpawnDestination destination, SpawnRequest request)
		{
			if (m_network == null || !CanSpawnItems())
			{
				return false;
			}
			m_network.Send(request);
			return true;
		}

		private bool SpawnCreature(SpawnRequest request)
		{
			if (m_network == null || !CanSpawnCreatures())
			{
				return false;
			}
			m_network.Send(request);
			return true;
		}

		private static KeyCode ParseKey(string name)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			return ParseKey(name, (KeyCode)287);
		}

		private static KeyCode ParseKey(string name, KeyCode fallback)
		{
			//IL_000d: 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)
			if (!Enum.TryParse<KeyCode>(name, ignoreCase: true, out KeyCode result))
			{
				return fallback;
			}
			return result;
		}
	}
	public static class ModVersion
	{
		public const string Value = "1.0.1";
	}
}
namespace VisualItemSpawner.UI
{
	public sealed class CreatureBrowser
	{
		private sealed class Card
		{
			public CreatureEntry? Entry;

			public Image Background;

			public Image Icon;

			public Image Selected;

			public TextMeshProUGUI Label;

			public Button Button;
		}

		private struct SubcategoryTab
		{
			public CreatureSubcategory Subcategory;

			public string Faction;
		}

		private const float WindowWidth = 1500f;

		private const float WindowHeight = 860f;

		private const float DetailsWidth = 340f;

		private const float GridMargin = 14f;

		private const float GridGap = 8f;

		private const float GridTop = 150f;

		private const float GridBottom = 74f;

		private const float ScrollbarWidth = 6f;

		private const float SearchHeight = 34f;

		private const float CategoryHeight = 32f;

		private const float SubcategoryHeight = 26f;

		private const float CategoryTop = -48f;

		private const float SubcategoryTop = -84f;

		private static int _cardSize = 120;

		private static int _cardPadding = 8;

		private static readonly int[] s_cardSizeSteps = new int[6] { 56, 68, 76, 92, 120, 140 };

		private static readonly int[] s_cardPaddingSteps = new int[6] { 2, 3, 4, 5, 8, 10 };

		private const int MinQuantity = 1;

		private const int MaxQuantity = 20;

		private readonly CreatureCatalog m_catalog;

		private readonly FallbackSpriteFactory m_sprites = new FallbackSpriteFactory();

		private readonly Func<SpawnRequest, bool> m_spawn;

		private readonly Func<bool> m_canSpawn;

		private readonly Func<SpawnDestination, SpawnRequest, bool> m_spawnItem;

		private readonly Func<bool> m_canSpawnItems;

		private CreatureImageProvider? m_images;

		private readonly List<Card> m_cards = new List<Card>(MaxItemsPerPage());

		private readonly List<CreatureEntry> m_visible = new List<CreatureEntry>(256);

		private readonly List<char> m_typed = new List<char>(16);

		private readonly StringBuilder m_searchText = new StringBuilder(64);

		private Canvas? m_canvas;

		private GameObject? m_root;

		private bool m_layoutLogged;

		private RectTransform? m_gridContent;

		private RectTransform? m_grid;

		private ScrollRect? m_gridScroll;

		private TextMeshProUGUI? m_searchLabel;

		private TextMeshProUGUI? m_statusLabel;

		private TextMeshProUGUI? m_countLabel;

		private Button? m_prevButton;

		private Button? m_nextButton;

		private TextMeshProUGUI? m_pageLabel;

		private Button? m_spawnButton;

		private Button? m_tamedButton;

		private Button? m_giveLootButton;

		private Button? m_dropLootButton;

		private readonly List<Button> m_quantityButtons = new List<Button>(2);

		private TextMeshProUGUI? m_quantityLabel;

		private readonly List<Button> m_levelButtons = new List<Button>(2);

		private TextMeshProUGUI? m_levelLabel;

		private TextMeshProUGUI? m_levelHint;

		private Image? m_detailIcon;

		private TextMeshProUGUI? m_detailName;

		private TextMeshProUGUI? m_detailStats;

		private CreatureCategory m_category;

		private CreatureSubcategory m_subcategory;

		private string m_faction = "";

		private Button[] m_categoryButtons = Array.Empty<Button>();

		private TextMeshProUGUI[] m_categoryLabels = Array.Empty<TextMeshProUGUI>();

		private RectTransform? m_subcategoryBar;

		private readonly List<GameObject> m_subcategoryObjects = new List<GameObject>();

		private readonly List<SubcategoryTab> m_subcategoryTabs = new List<SubcategoryTab>();

		private CreatureEntry? m_selected;

		private int m_quantity = 1;

		private bool m_tamed;

		private int m_level = 1;

		private int m_page;

		private int m_pageCount = 1;

		private bool m_searchFocused;

		private bool m_imagesReported;

		private bool m_favoritesOnly;

		private Button? m_favoritesButton;

		private Image? m_favoritesStar;

		private Button? m_favoriteButton;

		private Image? m_favoriteStar;

		private FavoritesStore? m_favorites;

		private string m_typingTarget = "";

		private readonly StringBuilder m_typingText = new StringBuilder(5);

		private double m_lastClick;

		private string m_lastUnavailableReason = "";

		private bool m_busy;

		private string m_status = "";

		private Color m_statusColor = new Color(0.85f, 0.82f, 0.72f);

		private readonly List<string> m_pendingThumbnails = new List<string>(256);

		private readonly HashSet<string> m_pendingThumbnailSet = new HashSet<string>();

		private const float ThumbnailFrameBudget = 0.004f;

		private CanvasScaler? m_scaler;

		private int m_zoomIndex = 4;

		private TextMeshProUGUI? m_zoomLabel;

		private Keyboard? m_keyboard;

		public Func<string>? UnavailableReason { get; set; }

		public FavoritesStore? Favorites
		{
			get
			{
				return m_favorites;
			}
			set
			{
				m_favorites = value;
			}
		}

		public int MaxQuantityPerRequest { get; set; } = 100;

		public bool TamedByDefault { get; set; }

		public int MaxCreatureLevel { get; set; } = 10;

		public CreatureImageProvider? Images
		{
			get
			{
				return m_images;
			}
			set
			{
				m_images = value;
			}
		}

		public bool IsOpen
		{
			get
			{
				if ((Object)(object)m_root != (Object)null)
				{
					return m_root.activeSelf;
				}
				return false;
			}
		}

		public event Action? Closed;

		public event Action? FavoritesChanged;

		private static int GridColumns()
		{
			float num = 1118f;
			return Mathf.Max(1, Mathf.FloorToInt((num + (float)_cardPadding) / (float)(_cardSize + _cardPadding)));
		}

		private static int GridRows()
		{
			float num = 636f;
			return Mathf.Max(1, Mathf.FloorToInt((num + (float)_cardPadding) / (float)(_cardSize + _cardPadding)));
		}

		private static int ItemsPerPage()
		{
			return Mathf.Max(1, GridColumns() * GridRows());
		}

		private static int MaxItemsPerPage()
		{
			float num = 1118f;
			float num2 = 636f;
			int num3 = Mathf.Max(1, Mathf.FloorToInt((num + (float)s_cardPaddingSteps[0]) / (float)(s_cardSizeSteps[0] + s_cardPaddingSteps[0])));
			int num4 = Mathf.Max(1, Mathf.FloorToInt((num2 + (float)s_cardPaddingSteps[0]) / (float)(s_cardSizeSteps[0] + s_cardPaddingSteps[0])));
			return Mathf.Max(1, num3 * num4);
		}

		public CreatureBrowser(CreatureCatalog catalog, Func<SpawnRequest, bool> spawn, Func<bool> canSpawn, Func<SpawnDestination, SpawnRequest, bool>? spawnItem = null, Func<bool>? canSpawnItems = null)
		{
			//IL_00e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			m_catalog = catalog ?? throw new ArgumentNullException("catalog");
			m_spawn = spawn ?? throw new ArgumentNullException("spawn");
			m_canSpawn = canSpawn ?? throw new ArgumentNullException("canSpawn");
			m_canSpawnItems = canSpawnItems ?? canSpawn;
			m_spawnItem = spawnItem ?? ((Func<SpawnDestination, SpawnRequest, bool>)((SpawnDestination destination, SpawnRequest request) => spawn(request)));
		}

		public void Open()
		{
			if (!IsOpen)
			{
				EnsureRoot();
				if (!((Object)(object)m_root == (Object)null))
				{
					m_root.SetActive(true);
					ZCursor.Show();
					ApplyFont();
					ResetTyping();
					m_searchFocused = true;
					InputBlock.SetTextEntry(value: true);
					m_tamed = TamedByDefault;
					RefreshSearchLabel();
					RefreshCategoryHighlight();
					RebuildSubcategoryBar();
					RebuildVisible();
					m_page = Mathf.Clamp(m_page, 0, m_pageCount - 1);
					RefreshPage();
					RefreshDetails();
					m_lastClick = 0.0;
					ReportPictures();
				}
			}
		}

		private void ReportPictures()
		{
			if (!m_imagesReported && m_images != null)
			{
				m_imagesReported = true;
				string text = m_images.DescribeFailures();
				if (m_images.FailedCount > 0)
				{
					Debug.LogWarning((object)("[VisualItemSpawner] " + text));
				}
				else
				{
					Debug.Log((object)("[VisualItemSpawner] " + text));
				}
			}
		}

		public void Close()
		{
			if (!((Object)(object)m_root == (Object)null) && m_root.activeSelf)
			{
				m_root.SetActive(false);
				ResetTyping();
				m_searchFocused = false;
				InputBlock.SetTextEntry(value: false);
				DetachKeyboard();
				ZCursor.Hide();
				m_pendingThumbnails.Clear();
				m_pendingThumbnailSet.Clear();
				this.Closed?.Invoke();
			}
		}

		public void Invalidate()
		{
			if (IsOpen)
			{
				RebuildVisible();
				RebuildSubcategoryBar();
				RefreshCategoryHighlight();
				RefreshPage();
				RefreshDetails();
			}
		}

		public void Update()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			if (!IsOpen)
			{
				return;
			}
			string text = UnavailableReason?.Invoke() ?? "";
			if (text != m_lastUnavailableReason)
			{
				m_lastUnavailableReason = text;
				SetStatus((text.Length == 0) ? "Ready to spawn." : text, new Color(0.9f, 0.78f, 0.55f));
				RefreshActionState();
			}
			LogLayoutOnce();
			HandleEscape();
			if (IsOpen)
			{
				HandleSearchKeys();
				if (m_typingTarget.Length == 0)
				{
					HandleNavigation();
					HandleShortcuts();
				}
				HandleZoomAndScroll();
				RenderThumbnails(0.004f);
			}
		}

		private void HandleZoomAndScroll()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			float y = Input.mouseScrollDelta.y;
			if (Mathf.Abs(y) < 0.01f)
			{
				return;
			}
			if (Input.GetKey((KeyCode)306) || Input.GetKey((KeyCode)305))
			{
				Zoom((y > 0f) ? 1 : (-1));
				return;
			}
			ScrollRect gridScroll = m_gridScroll;
			if (!((Object)(object)gridScroll == (Object)null))
			{
				float num = y * 0.15f;
				gridScroll.verticalNormalizedPosition = Mathf.Clamp01(gridScroll.verticalNormalizedPosition + num);
			}
		}

		public void Zoom(int direction)
		{
			int num = Mathf.Clamp(m_zoomIndex + direction, 0, s_cardSizeSteps.Length - 1);
			if (num != m_zoomIndex)
			{
				m_zoomIndex = num;
				_cardSize = s_cardSizeSteps[m_zoomIndex];
				_cardPadding = s_cardPaddingSteps[m_zoomIndex];
				m_layoutLogged = false;
				if ((Object)(object)m_zoomLabel != (Object)null)
				{
					((TMP_Text)m_zoomLabel).text = $"Tiles: {_cardSize}px";
				}
				RebuildVisible();
				RefreshGridLayout();
			}
		}

		public void Dispose()
		{
			DetachKeyboard();
			if ((Object)(object)m_root != (Object)null)
			{
				Object.Destroy((Object)(object)m_root);
				m_root = null;
			}
			m_sprites.Dispose();
			m_cards.Clear();
		}

		private void RebuildVisible()
		{
			m_visible.Clear();
			m_visible.AddRange(CreatureFilter.Apply(m_catalog.GetItems(), m_searchText.ToString(), m_category, m_subcategory, m_faction));
			if (m_favoritesOnly && m_favorites != null)
			{
				for (int num = m_visible.Count - 1; num >= 0; num--)
				{
					if (!m_favorites.IsCreatureFavorite(m_visible[num].Id))
					{
						m_visible.RemoveAt(num);
					}
				}
			}
			int num2 = ItemsPerPage();
			m_pageCount = Mathf.Max(1, Mathf.CeilToInt((float)m_visible.Count / (float)num2));
			m_page = Mathf.Clamp(m_page, 0, m_pageCount - 1);
			if (m_selected != null && !m_visible.Contains(m_selected))
			{
				m_selected = null;
			}
			if (m_selected == null && m_visible.Count > 0)
			{
				m_selected = m_visible[0];
				SyncSelectionToEntry();
			}
			EnqueueThumbnails();
		}

		private void RefreshPage()
		{
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Unknown result type (might be due to invalid IL or missing references)
			int num = ItemsPerPage();
			int num2 = m_page * num;
			int num3 = Mathf.Min(num, Mathf.Max(0, m_visible.Count - num2));
			for (int i = 0; i < m_cards.Count; i++)
			{
				Card card = m_cards[i];
				bool flag = i < num3;
				((Component)card.Background).gameObject.SetActive(flag);
				if (!flag)
				{
					card.Entry = null;
					continue;
				}
				CreatureEntry creatureEntry = (card.Entry = m_visible[num2 + i]);
				((TMP_Text)card.Label).text = ((m_favorites != null && m_favorites.IsCreatureFavorite(creatureEntry.Id)) ? "★ " : "") + creatureEntry.Name;
				card.Icon.sprite = m_sprites.PlaceholderIcon;
				((Graphic)card.Background).color = new Color(0.15f, 0.15f, 0.17f, 0.95f);
				((Behaviour)card.Selected).enabled = creatureEntry == m_selected;
			}
			if ((Object)(object)m_gridScroll != (Object)null)
			{
				m_gridScroll.verticalNormalizedPosition = 1f;
			}
			if ((Object)(object)m_countLabel != (Object)null)
			{
				((TMP_Text)m_countLabel).text = ((m_visible.Count == m_catalog.GetItems().Count) ? $"{m_visible.Count} creatures" : $"{m_visible.Count} / {m_catalog.GetItems().Count}");
			}
			if ((Object)(object)m_pageLabel != (Object)null)
			{
				((TMP_Text)m_pageLabel).text = $"{m_page + 1} / {m_pageCount}";
			}
			if ((Object)(object)m_prevButton != (Object)null)
			{
				((Selectable)m_prevButton).interactable = m_page > 0;
			}
			if ((Object)(object)m_nextButton != (Object)null)
			{
				((Selectable)m_nextButton).interactable = m_page < m_pageCount - 1;
			}
			RefreshPageIcons();
			EnqueueThumbnails();
			if (m_visible.Count == 0)
			{
				string message = ((m_catalog.GetItems().Count == 0) ? "No creatures are loaded yet." : $"No creatures match \"{m_searchText}\"{DescribeFilters()}.");
				if (m_favoritesOnly)
				{
					message = "No favorites yet. Open a creature's details and press ☆ to star it.";
				}
				SetStatus(message, new Color(0.9f, 0.78f, 0.55f));
			}
		}

		private string DescribeFilters()
		{
			List<string> list = new List<string>(2);
			if (m_category != CreatureCategory.All)
			{
				list.Add(CreatureCategoryInfo.DisplayName(m_category).ToLowerInvariant());
			}
			if (m_subcategory != CreatureSubcategory.None)
			{
				list.Add(CreatureSubcategoryInfo.DisplayName(m_subcategory).ToLowerInvariant());
			}
			if (!string.IsNullOrEmpty(m_faction))
			{
				list.Add(CreatureFactionInfo.DisplayName(m_faction).ToLowerInvariant());
			}
			if (list.Count != 0)
			{
				return " in " + string.Join(", ", list);
			}
			return string.Empty;
		}

		private void RefreshCategoryHighlight()
		{
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: 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_0078: 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)
			CreatureCategory[] all = CreatureCategoryInfo.All;
			for (int i = 0; i < m_categoryButtons.Length && i < all.Length; i++)
			{
				Button val = m_categoryButtons[i];
				if (!((Object)(object)val == (Object)null))
				{
					Graphic targetGraphic = ((Selectable)val).targetGraphic;
					Image val2 = (Image)(object)((targetGraphic is Image) ? targetGraphic : null);
					bool flag = all[i] == m_category;
					if ((Object)(object)val2 != (Object)null)
					{
						((Graphic)val2).color = (flag ? new Color(0.42f, 0.36f, 0.2f, 1f) : new Color(0.16f, 0.16f, 0.18f, 0.95f));
					}
					TextMeshProUGUI val3 = m_categoryLabels[i];
					if ((Object)(object)val3 != (Object)null)
					{
						int num = ((all[i] == CreatureCategory.All) ? m_catalog.GetItems().Count : m_catalog.CategoryCount(all[i]));
						((TMP_Text)val3).text = Localize(all[i]) + "  " + num;
					}
				}
			}
			if ((Object)(object)m_favoritesButton != (Object)null)
			{
				Graphic targetGraphic2 = ((Selectable)m_favoritesButton).targetGraphic;
				Image val4 = (Image)(object)((targetGraphic2 is Image) ? targetGraphic2 : null);
				if ((Object)(object)val4 != (Object)null)
				{
					((Graphic)val4).color = (m_favoritesOnly ? new Color(0.42f, 0.36f, 0.2f, 1f) : new Color(0.16f, 0.16f, 0.18f, 0.95f));
				}
			}
			if ((Object)(object)m_favoritesStar != (Object)null)
			{
				((Graphic)m_favoritesStar).color = (m_favoritesOnly ? new Color(1f, 0.85f, 0.4f, 1f) : new Color(0.45f, 0.43f, 0.4f, 1f));
			}
		}

		private void ToggleFavoritesOnly()
		{
			m_favoritesOnly = !m_favoritesOnly;
			RefreshCategoryHighlight();
			RebuildVisible();
			RefreshPage();
		}

		private void SelectCategory(CreatureCategory category)
		{
			if (m_category != category)
			{
				m_category = category;
				ResetTyping();
				m_subcategory = CreatureSubcategory.None;
				m_faction = "";
				RebuildSubcategoryBar();
				RefreshCategoryHighlight();
				RebuildVisible();
				RefreshPage();
				RefreshDetails();
			}
		}

		private void SelectSubcategory(SubcategoryTab tab)
		{
			m_subcategory = tab.Subcategory;
			m_faction = tab.Faction;
			ResetTyping();
			RefreshSubcategoryHighlight();
			RebuildVisible();
			RefreshPage();
			RefreshDetails();
		}

		private List<string> AvailableFactions(CreatureCategory category)
		{
			List<string> list = new List<string>();
			HashSet<string> hashSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
			IReadOnlyList<CreatureEntry> items = m_catalog.GetItems();
			for (int i = 0; i < items.Count; i++)
			{
				CreatureEntry creatureEntry = items[i];
				if (!string.IsNullOrEmpty(creatureEntry.Faction) && (category == CreatureCategory.All || creatureEntry.Category == category) && (m_subcategory != CreatureSubcategory.Tameable || creatureEntry.IsTameable) && (m_subcategory != CreatureSubcategory.Wild || !creatureEntry.IsTameable) && hashSet.Add(creatureEntry.Faction))
				{
					list.Add(creatureEntry.Faction);
				}
			}
			list.Sort(StringComparer.OrdinalIgnoreCase);
			return list;
		}

		private static string Localize(CreatureCategory category)
		{
			string text = CreatureCategoryInfo.TranslationKey(category);
			string text2 = SafeLocalize(text);
			if (!string.IsNullOrEmpty(text2) && !(text2 == text))
			{
				return text2;
			}
			return CreatureCategoryInfo.DisplayName(category);
		}

		private static string Localize(CreatureSubcategory subcategory)
		{
			string text = CreatureSubcategoryInfo.TranslationKey(subcategory);
			string text2 = SafeLocalize(text);
			if (!string.IsNullOrEmpty(text2) && !(text2 == text))
			{
				return text2;
			}
			return CreatureSubcategoryInfo.DisplayName(subcategory);
		}

		private static string SafeLocalize(string key)
		{
			Localization instance = Localization.instance;
			if (instance == null)
			{
				return "";
			}
			try
			{
				return instance.Localize(key);
			}
			catch (Exception)
			{
				return "";
			}
		}

		private void RefreshSubcategoryHighlight()
		{
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			for (int i = 0; i < m_subcategoryObjects.Count && i < m_subcategoryTabs.Count; i++)
			{
				GameObject val = m_subcategoryObjects[i];
				if (!((Object)(object)val == (Object)null))
				{
					Button component = val.GetComponent<Button>();
					SubcategoryTab subcategoryTab = m_subcategoryTabs[i];
					bool flag = subcategoryTab.Subcategory == m_subcategory && string.Equals(subcategoryTab.Faction, m_faction, StringComparison.OrdinalIgnoreCase);
					Image val2 = (Image)(((Object)(object)component != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
					if ((Object)(object)val2 != (Object)null)
					{
						((Graphic)val2).color = (flag ? new Color(0.36f, 0.32f, 0.19f, 1f) : new Color(0.14f, 0.14f, 0.16f, 0.95f));
					}
				}
			}
		}

		private void RefreshDetails()
		{
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			CreatureEntry selected = m_selected;
			bool flag = selected != null;
			m_canSpawn();
			RefreshDetailIcon();
			if ((Object)(object)m_favoriteButton != (Object)null)
			{
				bool flag2 = flag && m_favorites != null && m_favorites.IsCreatureFavorite(selected.Id);
				if ((Object)(object)m_favoriteStar != (Object)null)
				{
					((Graphic)m_favoriteStar).color = (flag2 ? new Color(1f, 0.85f, 0.4f, 1f) : new Color(0.45f, 0.43f, 0.4f, 1f));
				}
				((Selectable)m_favoriteButton).interactable = flag;
			}
			if ((Object)(object)m_detailName != (Object)null)
			{
				((TMP_Text)m_detailName).text = (flag ? selected.Name : "No creature selected");
			}
			if ((Object)(object)m_detailStats != (Object)null)
			{
				((TMP_Text)m_detailStats).text = (flag ? Describe(selected) : string.Empty);
			}
			bool flag3 = flag && selected.Drops.Count > 0;
			if ((Object)(object)m_giveLootButton != (Object)null)
			{
				((Component)m_giveLootButton).gameObject.SetActive(flag3);
			}
			if ((Object)(object)m_dropLootButton != (Object)null)
			{
				((Component)m_dropLootButton).gameObject.SetActive(flag3);
			}
			if (flag && flag3 && (Object)(object)m_detailStats != (Object)null)
			{
				TextMeshProUGUI? detailStats = m_detailStats;
				((TMP_Text)detailStats).text = ((TMP_Text)detailStats).text + $"\nDrops: {selected.Drops.Count} kinds";
			}
			if ((Object)(object)m_quantityLabel != (Object)null)
			{
				((TMP_Text)m_quantityLabel).text = m_quantity.ToString();
			}
			if ((Object)(object)m_levelLabel != (Object)null)
			{
				((TMP_Text)m_levelLabel).text = m_level.ToString();
			}
			if ((Object)(object)m_levelHint != (Object)null)
			{
				((TMP_Text)m_levelHint).text = VisProtocol.DescribeCreatureLevel(m_level);
			}
			if ((Object)(object)m_tamedButton != (Object)null)
			{
				bool flag4 = flag && selected.IsTameable;
				((Selectable)m_tamedButton).interactable = flag4 && !m_busy;
				SetLabel(m_tamedButton, "Tamed: " + (m_tamed ? "On" : "Off"));
			}
			for (int i = 0; i < m_quantityButtons.Count; i++)
			{
				((Selectable)m_quantityButtons[i]).interactable = flag && !m_busy;
			}
			for (int j = 0; j < m_levelButtons.Count; j++)
			{
				((Selectable)m_levelButtons[j]).interactable = flag && !m_busy;
			}
			RefreshActionState();
		}

		private void RefreshDetailIcon()
		{
			if (!((Object)(object)m_detailIcon == (Object)null))
			{
				Sprite sprite = m_sprites.PlaceholderIcon;
				if (m_selected != null && m_images != null && m_images.TryGetImage(m_selected.Id, out Sprite sprite2) && (Object)(object)sprite2 != (Object)null)
				{
					sprite = sprite2;
				}
				m_detailIcon.sprite = sprite;
				((Behaviour)m_detailIcon).enabled = m_selected != null;
			}
		}

		private void ToggleFavorite()
		{
			CreatureEntry selected = m_selected;
			if (selected != null && m_favorites != null)
			{
				m_favorites.SetCreatureFavorite(selected.Id, !m_favorites.IsCreatureFavorite(selected.Id));
				this.FavoritesChanged?.Invoke();
				RefreshFavoriteIndicators();
				RefreshDetails();
			}
		}

		private void RefreshFavoriteIndicators()
		{
			for (int i = 0; i < m_cards.Count; i++)
			{
				Card card = m_cards[i];
				CreatureEntry entry = card.Entry;
				if (entry != null)
				{
					((TMP_Text)card.Label).text = ((m_favorites != null && m_favorites.IsCreatureFavorite(entry.Id)) ? "★ " : "") + entry.Name;
				}
			}
		}

		private void RefreshActionState()
		{
			bool interactable = m_selected != null && m_canSpawn() && !m_busy;
			if ((Object)(object)m_spawnButton != (Object)null)
			{
				((Selectable)m_spawnButton).interactable = interactable;
			}
			bool interactable2 = m_selected != null && m_selected.Drops.Count > 0 && m_canSpawnItems() && !m_busy;
			if ((Object)(object)m_giveLootButton != (Object)null)
			{
				((Selectable)m_giveLootButton).interactable = interactable2;
			}
			if ((Object)(object)m_dropLootButton != (Object)null)
			{
				((Selectable)m_dropLootButton).interactable = interactable2;
			}
		}

		private static string Describe(CreatureEntry entry)
		{
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append(entry.Id).Append('\n');
			stringBuilder.Append(CreatureCategoryInfo.DisplayName(entry.Category));
			if (!string.IsNullOrEmpty(entry.Faction))
			{
				stringBuilder.Append("  ").Append(CreatureFactionInfo.DisplayName(entry.Faction));
			}
			if (!string.IsNullOrEmpty(entry.Biome))
			{
				stringBuilder.Append('\n').Append("Group ").Append(CreatureBiomeInfo.DisplayName(entry.Biome));
			}
			stringBuilder.Append('\n');
			stringBuilder.Append("Health ").Append(entry.Health.ToString("0"));
			if (entry.IsBoss)
			{
				stringBuilder.Append('\n').Append("Boss");
			}
			stringBuilder.Append('\n').Append(entry.IsTameable ? "Tameable" : "Wild");
			if (!string.IsNullOrEmpty(entry.Group))
			{
				stringBuilder.Append('\n').Append("Group ").Append(entry.Group);
			}
			return stringBuilder.ToString();
		}

		private void SetStatus(string message, Color color)
		{
			//IL_0008: 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_002e: Unknown result type (might be due to invalid IL or missing references)
			m_status = message;
			m_statusColor = color;
			if ((Object)(object)m_statusLabel != (Object)null)
			{
				((TMP_Text)m_statusLabel).text = message;
				((Graphic)m_statusLabel).color = color;
			}
		}

		private void ChangePage(int delta)
		{
			int num = Mathf.Clamp(m_page + delta, 0, m_pageCount - 1);
			if (num != m_page)
			{
				m_page = num;
				ResetTyping();
				RefreshPage();
			}
		}

		private void SyncSelectionToEntry()
		{
			m_quantity = Mathf.Clamp(m_quantity, 1, QuantityCap());
		}

		private int QuantityCap()
		{
			return Mathf.Clamp(MaxQuantityPerRequest, 1, 20);
		}

		private int LevelCap()
		{
			return Mathf.Clamp(MaxCreatureLevel, 1, 50);
		}

		private void OnCardClicked(Card card)
		{
			CreatureEntry entry = card.Entry;
			if (entry != null)
			{
				ResetTyping();
				double realtimeSinceStartupAsDouble = Time.realtimeSinceStartupAsDouble;
				bool num = entry == m_selected;
				m_selected = entry;
				SyncSelectionToEntry();
				m_tamed = entry.IsTameable && m_tamed;
				if (num && realtimeSinceStartupAsDouble - m_lastClick < 0.4)
				{
					Submit();
					m_lastClick = 0.0;
				}
				else
				{
					m_lastClick = realtimeSinceStartupAsDouble;
				}
				RefreshPage();
				RefreshDetails();
			}
		}

		private void OnQuantityStep(int delta)
		{
			if (m_selected != null)
			{
				int num = QuantityCap();
				m_quantity = ((m_quantity + delta <= 0) ? m_quantity : Mathf.Clamp(m_quantity + delta, 1, num));
				RefreshDetails();
			}
		}

		private void OnTamedToggled()
		{
			if (m_selected != null && m_selected.IsTameable)
			{
				m_tamed = !m_tamed;
				RefreshDetails();
			}
		}

		private void OnLevelStep(int delta)
		{
			if (m_selected != null)
			{
				m_level = Mathf.Clamp(m_level + delta, 1, LevelCap());
				RefreshDetails();
			}
		}

		private void Submit()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_013f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			CreatureEntry selected = m_selected;
			if (selected == null)
			{
				SetStatus("Select a creature first.", new Color(0.9f, 0.65f, 0.45f));
				return;
			}
			if (m_busy)
			{
				SetStatus("Waiting for the previous request...", new Color(0.9f, 0.78f, 0.55f));
				return;
			}
			if (!m_canSpawn())
			{
				SetStatus(NoPermissionReason(), new Color(0.9f, 0.55f, 0.45f));
				return;
			}
			SpawnRequest arg = new SpawnRequest
			{
				PrefabId = selected.Id,
				Quantity = m_quantity,
				Kind = SpawnKind.Creature,
				Tamed = m_tamed,
				Level = m_level,
				Destination = SpawnDestination.Ground
			};
			m_busy = true;
			RefreshActionState();
			if (m_spawn(arg))
			{
				if (m_busy)
				{
					SetStatus($"Requested {selected.Name} x{m_quantity}...", new Color(0.85f, 0.82f, 0.72f));
				}
			}
			else
			{
				m_busy = false;
				RefreshActionState();
				SetStatus("Request could not be sent.", new Color(0.9f, 0.55f, 0.45f));
			}
		}

		private void SubmitLoot(SpawnDestination destination)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_017a: Unknown result type (might be due to invalid IL or missing references)
			CreatureEntry selected = m_selected;
			if (selected == null)
			{
				SetStatus("Select a creature first.", new Color(0.9f, 0.65f, 0.45f));
				return;
			}
			if (m_busy)
			{
				SetStatus("Waiting for the previous request...", new Color(0.9f, 0.78f, 0.55f));
				return;
			}
			if (!m_canSpawnItems())
			{
				SetStatus("You do not have permission to spawn items on this server.", new Color(0.9f, 0.55f, 0.45f));
				return;
			}
			if (selected.Drops.Count == 0)
			{
				SetStatus("This creature drops nothing.", new Color(0.9f, 0.78f, 0.55f));
				return;
			}
			int num = 0;
			for (int i = 0; i < selected.Drops.Count; i++)
			{
				CreatureDropInfo creatureDropInfo = selected.Drops[i];
				SpawnRequest arg = new SpawnRequest
				{
					PrefabId = creatureDropInfo.PrefabId,
					Quantity = creatureDropInfo.Amount * m_quantity,
					Quality = 1,
					Variant = 0,
					Kind = SpawnKind.Item,
					Destination = destination
				};
				if (m_spawnItem(destination, arg))
				{
					num++;
				}
			}
			SetStatus($"Requested {selected.Name} drops x{m_quantity} ({num} of {selected.Drops.Count} kinds)...", new Color(0.85f, 0.82f, 0.72f));
		}

		private string NoPermissionReason()
		{
			return UnavailableReason?.Invoke() ?? "You do not have permission to spawn creatures on this server.";
		}

		public void ShowOutcome(SpawnOutcome outcome)
		{
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			m_busy = false;
			if (IsOpen)
			{
				RefreshActionState();
				if (outcome.Result.IsSuccess)
				{
					string text = outcome.Request?.PrefabId ?? "creature";
					string text2 = (outcome.ClientApplyFailed ? " Server approved it but this client could not deliver it." : string.Empty);
					SetStatus($"Spawned {outcome.Result.DeliveredQuantity} x {text}. {outcome.Result.Message}{text2}", new Color(0.62f, 0.85f, 0.55f));
				}
				else
				{
					SetStatus($"{outcome.Result.Status}: {outcome.Result.Message}", new Color(0.9f, 0.55f, 0.45f));
				}
			}
		}

		private void EnqueueThumbnails()
		{
			m_pendingThumbnails.Clear();
			m_pendingThumbnailSet.Clear();
			int num = ItemsPerPage();
			int num2 = m_page * num;
			int num3 = Mathf.Min(num, Mathf.Max(0, m_visible.Count - num2));
			for (int i = 0; i < num3; i++)
			{
				CreatureEntry creatureEntry = m_visible[num2 + i];
				if (creatureEntry != null && m_images != null)
				{
					string id = creatureEntry.Id;
					if (!m_images.TryGetImage(id, out Sprite _) && !m_pendingThumbnailSet.Contains(id))
					{
						m_pendingThumbnailSet.Add(id);
						m_pendingThumbnails.Add(id);
					}
				}
			}
		}

		private void RenderThumbnails(float budgetSeconds)
		{
			if (m_images == null || m_pendingThumbnails.Count == 0 || !IsOpen)
			{
				return;
			}
			double realtimeSinceStartupAsDouble = Time.realtimeSinceStartupAsDouble;
			bool flag = false;
			while (m_pendingThumbnails.Count > 0)
			{
				string text = m_pendingThumbnails[0];
				m_pendingThumbnails.RemoveAt(0);
				m_pendingThumbnailSet.Remove(text);
				m_images.GetImage(text);
				flag = true;
				RefreshPageIcons();
				RefreshDetailIcon();
				if (budgetSeconds <= 0f || Time.realtimeSinceStartupAsDouble - realtimeSinceStartupAsDouble >= (double)budgetSeconds)
				{
					break;
				}
			}
			if (flag)
			{
				RefreshPageIcons();
				RefreshDetailIcon();
			}
		}

		private void RefreshPageIcons()
		{
			int num = ItemsPerPage();
			int num2 = m_page * num;
			Mathf.Min(num, Mathf.Max(0, m_visible.Count - num2));
			for (int i = 0; i < m_cards.Count; i++)
			{
				Card card = m_cards[i];
				if (!((Component)card.Background).gameObject.activeSelf)
				{
					continue;
				}
				CreatureEntry entry = card.Entry;
				if (entry != null)
				{
					if (m_images == null || !m_images.TryGetImage(entry.Id, out Sprite sprite) || (Object)(object)sprite == (Object)null)
					{
						card.Icon.sprite = m_sprites.PlaceholderIcon;
						((Behaviour)card.Icon).enabled = true;
					}
					else
					{
						card.Icon.sprite = sprite;
						((Behaviour)card.Icon).enabled = true;
					}
				}
			}
		}

		private void RefreshGridLayout()
		{
			//IL_0074: 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_00be: 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)
			if ((Object)(object)m_gridContent != (Object)null)
			{
				while (m_cards.Count < ItemsPerPage())
				{
					Card card = BuildCard(m_gridContent);
					LayoutCard(card);
					m_cards.Add(card);
				}
			}
			GridLayoutGroup val = (((Object)(object)m_gridContent != (Object)null) ? ((Component)m_gridContent).GetComponent<GridLayoutGroup>() : null);
			if ((Object)(object)val != (Object)null)
			{
				val.cellSize = new Vector2((float)_cardSize, (float)_cardSize);
				val.spacing = new Vector2((float)_cardPadding, (float)_cardPadding);
				val.constraintCount = GridColumns();
			}
			if ((Object)(object)m_grid != (Object)null)
			{
				m_grid.offsetMin = new Vector2(14f, 74f);
				m_grid.offsetMax = new Vector2(-362f, -150f);
			}
			for (int i = 0; i < m_cards.Count; i++)
			{
				LayoutCard(m_cards[i]);
			}
			m_pageCount = Mathf.Max(1, Mathf.CeilToInt((float)m_visible.Count / (float)ItemsPerPage()));
			m_page = Mathf.Clamp(m_page, 0, m_pageCount - 1);
			RefreshPage();
		}

		private void AttachKeyboard()
		{
			Keyboard current = Keyboard.current;
			if (current != null && m_keyboard != current)
			{
				DetachKeyboard();
				m_keyboard = current;
				m_keyboard.onTextInput += OnTypedCharacter;
			}
		}

		private void DetachKeyboard()
		{
			if (m_keyboard != null)
			{
				m_keyboard.onTextInput -= OnTypedCharacter;
				m_keyboard = null;
			}
			m_typed.Clear();
		}

		private void OnTypedCharacter(char character)
		{
			if (m_typed.Count < 32)
			{
				m_typed.Add(character);
			}
		}

		private void HandleSearchKeys()
		{
			AttachKeyboard();
			if (!m_searchFocused)
			{
				m_typed.Clear();
				return;
			}
			if (m_typingTarget.Length > 0)
			{
				HandleTypingKeys();
				return;
			}
			for (int i = 0; i < m_typed.Count; i++)
			{
				char c = m_typed[i];
				if (!char.IsControl(c) && m_searchText.Length < 64)
				{
					m_searchText.Append(c);
				}
			}
			bool flag = m_typed.Count > 0;
			m_typed.Clear();
			if (ZInput.GetKeyDown((KeyCode)8, true))
			{
				RemoveLastCharacter();
				flag = true;
			}
			if (ZInput.GetKeyDown((KeyCode)127, true))
			{
				m_searchText.Clear();
				flag = true;
			}
			if (flag)
			{
				CommitSearch();
			}
			if (ZInput.GetKeyDown((KeyCode)13, true) || ZInput.GetKeyDown((KeyCode)271, true))
			{
				Submit();
			}
		}

		private void HandleEscape()
		{
			if (ZInput.GetKeyDown((KeyCode)27, true))
			{
				if (m_typingTarget.Length > 0)
				{
					CancelTyping();
				}
				else if (m_searchText.Length > 0)
				{
					m_searchText.Clear();
					CommitSearch();
				}
				else
				{
					Close();
				}
			}
		}

		private void BeginTyping(string target)
		{
			if (m_selected != null)
			{
				m_typingTarget = target;
				m_typingText.Clear();
				RefreshTypingLabel();
			}
		}

		private void HandleTypingKeys()
		{
			for (int i = 0; i < m_typed.Count; i++)
			{
				char c = m_typed[i];
				if (char.IsDigit(c) && m_typingText.Length < 5)
				{
					m_typingText.Append(c);
				}
			}
			m_typed.Clear();
			if (ZInput.GetKeyDown((KeyCode)8, true))
			{
				if (m_typingText.Length <= 0)
				{
					CancelTyping();
					return;
				}
				m_typingText.Length--;
			}
			if (ZInput.GetKeyDown((KeyCode)127, true))
			{
				m_typingText.Clear();
			}
			RefreshTypingLabel();
			if (ZInput.GetKeyDown((KeyCode)13, true) || ZInput.GetKeyDown((KeyCode)271, true))
			{
				CommitTyping();
			}
		}

		private void CommitTyping()
		{
			CreatureEntry? selected = m_selected;
			string typingTarget = m_typingTarget;
			string text = m_typingText.ToString();
			ResetTyping();
			if (selected == null || text.Length == 0)
			{
				RefreshDetails();
				return;
			}
			if (typingTarget == "quantity")
			{
				m_quantity = NumericInput.Parse(text, 1, QuantityCap(), m_quantity);
			}
			else if (typingTarget == "level")
			{
				m_level = NumericInput.Parse(text, 1, LevelCap(), m_level);
			}
			RefreshDetails();
		}

		private void CancelTyping()
		{
			if (m_typingTarget.Length != 0)
			{
				ResetTyping();
				RefreshDetails();
			}
		}

		private void ResetTyping()
		{
			m_typingTarget = "";
			m_typingText.Clear();
		}

		private void RefreshTypingLabel()
		{
			string text = ((m_typingText.Length > 0) ? (m_typingText.ToString() + "_") : "_");
			if (m_typingTarget == "quantity" && (Object)(object)m_quantityLabel != (Object)null)
			{
				((TMP_Text)m_quantityLabel).text = text;
			}
			else if (m_typingTarget == "level" && (Object)(object)m_levelLabel != (Object)null)
			{
				((TMP_Text)m_levelLabel).text = text;
			}
		}

		private void RemoveLastCharacter()
		{
			if (m_searchText.Length > 0)
			{
				m_searchText.Length--;
			}
		}

		private void CommitSearch()
		{
			ResetTyping();
			m_page = 0;
			RebuildVisible();
			RefreshPage();
			RefreshDetails();
			RefreshSearchLabel();
		}

		private void RefreshSearchLabel()
		{
			//IL_0070: 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)
			if ((Object)(object)m_searchLabel != (Object)null)
			{
				((TMP_Text)m_searchLabel).text = ((m_searchText.Length == 0) ? "Search creatures..." : m_searchText.ToString());
				((Graphic)m_searchLabel).color = ((m_searchText.Length == 0) ? new Color(0.62f, 0.6f, 0.56f) : new Color(0.92f, 0.9f, 0.82f));
			}
		}

		private void HandleNavigation()
		{
			if (m_visible.Count == 0)
			{
				return;
			}
			int num = ((m_selected != null) ? m_visible.IndexOf(m_selected) : 0);
			if (num < 0)
			{
				num = 0;
			}
			int num2 = GridColumns();
			int num3 = num;
			if (ZInput.GetKeyDown((KeyCode)274, true))
			{
				num3 = Mathf.Min(m_visible.Count - 1, num + num2);
			}
			else if (ZInput.GetKeyDown((KeyCode)273, true))
			{
				num3 = Mathf.Max(0, num - num2);
			}
			else if (ZInput.GetKeyDown((KeyCode)275, true))
			{
				num3 = Mathf.Min(m_visible.Count - 1, num + 1);
			}
			else if (ZInput.GetKeyDown((KeyCode)276, true))
			{
				num3 = Mathf.Max(0, num - 1);
			}
			else if (ZInput.GetKeyDown((KeyCode)9, true))
			{
				num3 = (num + 1) % m_visible.Count;
			}
			else
			{
				if (ZInput.GetKeyDown((KeyCode)281, true))
				{
					ChangePage(1);
					return;
				}
				if (ZInput.GetKeyDown((KeyCode)280, true))
				{
					ChangePage(-1);
					return;
				}
			}
			if (num3 != num && num3 >= 0 && num3 < m_visible.Count)
			{
				Select(m_visible[num3]);
			}
		}

		private void Select(CreatureEntry entry)
		{
			ResetTyping();
			m_selected = entry;
			SyncSelectionToEntry();
			EnsureVisibleOnPage(entry);
			RefreshPage();
			RefreshDetails();
		}

		private void EnsureVisibleOnPage(CreatureEntry entry)
		{
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			int num = m_visible.IndexOf(entry);
			if (num >= 0)
			{
				int num2 = ItemsPerPage();
				int num3 = num / num2;
				if (num3 != m_page)
				{
					m_page = num3;
					RefreshPage();
				}
				int num4 = num % num2;
				if (!((Object)(object)m_gridContent == (Object)null) && !((Object)(object)m_gridScroll == (Object)null) && m_cards.Count != 0)
				{
					int num5 = GridColumns();
					int num6 = Mathf.Max(1, num2 / num5);
					int num7 = num4 / num5;
					float num8 = num6 * (_cardSize + _cardPadding);
					Rect rect = m_gridScroll.viewport.rect;
					float height = ((Rect)(ref rect)).height;
					float num9 = ((height <= 0f) ? 1f : (1f - (float)(num7 * (_cardSize + _cardPadding)) / Mathf.Max(1f, num8 - height)));
					m_gridScroll.verticalNormalizedPosition = Mathf.Clamp01(num9);
				}
			}
		}

		private void HandleShortcuts()
		{
			if (m_selected != null && ZInput.GetKey((KeyCode)306, true))
			{
				if (ZInput.GetKeyDown((KeyCode)113, true))
				{
					OnQuantityStep(-1);
				}
				if (ZInput.GetKeyDown((KeyCode)101, true))
				{
					OnQuantityStep(1);
				}
				if (ZInput.GetKeyDown((KeyCode)116, true))
				{
					OnTamedToggled();
				}
			}
		}

		private void EnsureRoot()
		{
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)m_root != (Object)null)
			{
				return;
			}
			m_sprites.EnsureBuilt();
			try
			{
				m_root = BuildWindow();
			}
			catch (Exception arg)
			{
				m_root = null;
				m_canvas = null;
				Debug.LogError((object)$"[VisualItemSpawner] creature browser could not be created: {arg}");
				SetStatus("The creature browser could not be created. See the BepInEx log.", new Color(0.9f, 0.45f, 0.4f));
			}
		}

		private GameObject BuildWindow()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_004d: 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)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("VisualItemSpawnerCreatures", new Type[1] { typeof(RectTransform) });
			Canvas val2 = val.AddComponent<Canvas>();
			val2.sortingOrder = 100;
			val2.renderMode = (RenderMode)0;
			CanvasScaler val3 = val.AddComponent<CanvasScaler>();
			val3.uiScaleMode = (ScaleMode)1;
			val3.referenceResolution = new Vector2(1920f, 1080f);
			val3.matchWidthOrHeight = 0.5f;
			m_scaler = val3;
			val.AddComponent<GraphicRaycaster>();
			val.AddComponent<GuiScaler>();
			m_canvas = val2;
			RectTransform val4 = UiFactory.CreateRect("Panel", val.transform);
			UiFactory.Anchor(val4, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(1500f, 860f));
			Image val5 = ((Component)val4).gameObject.AddComponent<Image>();
			val5.sprite = m_sprites.Panel;
			((Graphic)val5).color = new Color(0.07f, 0.07f, 0.08f, 0.97f);
			val5.type = (Type)1;
			Button obj = ((Component)val4).gameObject.AddComponent<Button>();
			((Selectable)obj).transition = (Transition)0;
			((Selectable)obj).targetGraphic = (Graphic)(object)val5;
			BuildHeader(val4);
			BuildCategoryBar(val4);
			BuildSubcategoryBar(val4);
			BuildGrid(val4);
			BuildDetails(val4);
			BuildStatusBar(val4);
			return ((Component)val4).gameObject;
		}

		private RectTransform BuildHeader(RectTransform root)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0181: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: 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_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: 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)
			//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_0229: Expected O, but got Unknown
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_024a: Expected O, but got Unknown
			//IL_0265: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Unknown result type (might be due to invalid IL or missing references)
			//IL_029d: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0311: Unknown result type (might be due to invalid IL or missing references)
			//IL_0320: Unknown result type (might be due to invalid IL or missing references)
			//IL_032f: 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_0357: Expected O, but got Unknown
			//IL_036e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0378: Expected O, but got Unknown
			//IL_0399: Unknown result type (might be due to invalid IL or missing references)
			//IL_03a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_03df: Expected O, but got Unknown
			//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0400: Expected O, but got Unknown
			RectTransform val = UiFactory.CreateRect("Header", (Transform)(object)root);
			UiFactory.Anchor(val, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(0f, 0f), new Vector2(0f, 44f));
			val.pivot = new Vector2(0f, 1f);
			val.anchorMax = new Vector2(1f, 1f);
			val.sizeDelta = new Vector2(0f, 44f);
			Image obj = ((Component)val).gameObject.AddComponent<Image>();
			obj.sprite = m_sprites.PanelHeader;
			((Graphic)obj).color = new Color(0.13f, 0.12f, 0.1f, 0.98f);
			obj.type = (Type)1;
			TextMeshProUGUI obj2 = UiFactory.CreateText("Title", (Transform)(object)val, 20f, new Color(0.9f, 0.84f, 0.66f), (TextAlignmentOptions)513);
			UiFactory.Anchor(((TMP_Text)obj2).rectTransform, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(14f, 0f), new Vector2(420f, 30f));
			((TMP_Text)obj2).text = "Creature Spawner";
			TextMeshProUGUI obj3 = UiFactory.CreateText("Hint", (Transform)(object)val, 14f, new Color(0.72f, 0.7f, 0.64f), (TextAlignmentOptions)516);
			UiFactory.Anchor(((TMP_Text)obj3).rectTransform, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-266f, 0f), new Vector2(780f, 30f));
			((TMP_Text)obj3).text = "Type to search   Arrows/Tab move   Ctrl+Q/E quantity   Enter spawn   T tamed";
			Button obj4 = UiFactory.CreateButton("ZoomOut", (Transform)(object)val, m_sprites.Button, 15f);
			UiFactory.Anchor((RectTransform)((Component)obj4).transform, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-204f, 0f), new Vector2(28f, 28f));
			SetLabel(obj4, "-");
			((UnityEvent)obj4.onClick).AddListener((UnityAction)delegate
			{
				Zoom(-1);
			});
			m_zoomLabel = UiFactory.CreateText("Zoom", (Transform)(object)val, 14f, new Color(0.82f, 0.8f, 0.72f), (TextAlignmentOptions)514);
			UiFactory.Anchor(((TMP_Text)m_zoomLabel).rectTransform, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-120f, 0f), new Vector2(80f, 28f));
			((Graphic)m_zoomLabel).raycastTarget = false;
			((TMP_Text)m_zoomLabel).text = $"Tiles: {_cardSize}px";
			Button obj5 = UiFactory.CreateButton("ZoomIn", (Transform)(object)val, m_sprites.Button, 15f);
			UiFactory.Anchor((RectTransform)((Component)obj5).transform, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-90f, 0f), new Vector2(28f, 28f));
			SetLabel(obj5, "+");
			((UnityEvent)obj5.onClick).AddListener((UnityAction)delegate
			{
				Zoom(1);
			});
			Button obj6 = UiFactory.CreateButton("Close", (Transform)(object)val, m_sprites.Button, 15f);
			UiFactory.Anchor((RectTransform)((Component)obj6).transform, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-14f, 0f), new Vector2(70f, 28f));
			SetLabel(obj6, "Close");
			((UnityEvent)obj6.onClick).AddListener(new UnityAction(Close));
			return val;
		}

		private void BuildCategoryBar(RectTransform root)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_005b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Expected O, but got Unknown
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016d: Expected O, but got Unknown
			//IL_01c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Expected O, but got Unknown
			//IL_0286: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b4: Expected O, but got Unknown
			float num = 1124f;
			RectTransform val = UiFactory.CreateRect("CategoryBar", (Transform)(object)root);
			UiFactory.Anchor(val, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(14f, -48f), new Vector2(num, 32f));
			val.anchorMax = new Vector2(1f, 1f);
			val.offsetMin = new Vector2(14f, -80f);
			val.offsetMax = new Vector2(-362f, -48f);
			CreatureCategory[] all = CreatureCategoryInfo.All;
			float num2 = num / (float)(all.Length + 1);
			m_categoryButtons = (Button[])(object)new Button[all.Length];
			m_categoryLabels = (TextMeshProUGUI[])(object)new TextMeshProUGUI[all.Length];
			for (int i = 0; i < all.Length; i++)
			{
				CreatureCategory category = all[i];
				Button val2 = UiFactory.CreateButton("Category" + i, (Transform)(object)val, m_sprites.Button, 14f);
				UiFactory.Anchor((RectTransform)((Component)val2).transform, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2((float)i * num2, 0f), new Vector2(num2 - 3f, 28f));
				((UnityEvent)val2.onClick).AddListener((UnityAction)delegate
				{
					SelectCategory(category);
				});
				m_categoryButtons[i] = val2;
				m_categoryLabels[i] = ((Component)val2).GetComponentInChildren<TextMeshProUGUI>();
			}
			m_favoritesButton = UiFactory.CreateButton("Favorites", (Transform)(object)val, m_sprites.Button, 14f);
			UiFactory.Anchor((RectTransform)((Component)m_favoritesButton).transform, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2((float)all.Length * num2, 0f), new Vector2(num2 - 3f, 28f));
			SetLabel(m_favoritesButton, "");
			RectTransform obj = UiFactory.CreateRect("Star", ((Component)m_favoritesButton).transform);
			UiFactory.Stretch(obj, 8f, 5f);
			Image val3 = ((Component)obj).gameObject.AddComponent<Image>();
			val3.sprite = m_sprites.Star;
			val3.preserveAspect = true;
			((Graphic)val3).raycastTarget = false;
			((Graphic)val3).color = new Color(0.45f, 0.43f, 0.4f, 1f);
			m_favoritesStar = val3;
			((UnityEvent)m_favoritesButton.onClick).AddListener(new UnityAction(ToggleFavoritesOnly));
		}

		private void BuildSubcategoryBar(RectTransform root)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = UiFactory.CreateRect("SubcategoryBar", (Transform)(object)root);
			UiFactory.Anchor(val, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(14f, -84f), new Vector2(1124f, 26f));
			val.anchorMax = new Vector2(1f, 1f);
			val.offsetMin = new Vector2(14f, -110f);
			val.offsetMax = new Vector2(-362f, -84f);
			m_subcategoryBar = val;
			RebuildSubcategoryBar();
		}

		private void RebuildSubcategoryBar()
		{
			RectTransform subcategoryBar = m_subcategoryBar;
			if ((Object)(object)subcategoryBar == (Object)null)
			{
				return;
			}
			for (int i = 0; i < m_subcategoryObjects.Count; i++)
			{
				if ((Object)(object)m_subcategoryObjects[i] != (Object)null)
				{
					Object.Destroy((Object)(object)m_subcategoryObjects[i]);
				}
			}
			m_subcategoryObjects.Clear();
			m_subcategoryTabs.Clear();
			CreatureSubcategory[] array = CreatureSubcategoryInfo.For(m_category);
			List<string> list = AvailableFactions(m_category);
			int num = array.Length + list.Count;
			if (num != 0)
			{
				float num2 = 1124f;
				float cell = Mathf.Min(150f, num2 / (float)num);
				int num3 = 0;
				foreach (CreatureSubcategory subcategory in array)
				{
					AddSubcategoryButton(subcategoryBar, num3++, cell, Localize(subcategory), new SubcategoryTab
					{
						Subcategory = subcategory,
						Faction = ""
					});
				}
				for (int k = 0; k < list.Count; k++)
				{
					AddSubcategoryButton(subcategoryBar, num3++, cell, CreatureFactionInfo.DisplayName(list[k]), new SubcategoryTab
					{
						Subcategory = CreatureSubcategory.None,
						Faction = list[k]
					});
				}
				RefreshSubcategoryHighlight();
			}
		}

		private void AddSubcategoryButton(RectTransform parent, int index, float cell, string label, SubcategoryTab tab)
		{
			//IL_003b: 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_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			Button val = UiFactory.CreateButton("Filter" + index, (Transform)(object)parent, m_sprites.Button, 13f);
			UiFactory.Anchor((RectTransform)((Component)val).transform, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2((float)index * cell, 0f), new Vector2(cell - 3f, 23f));
			SetLabel(val, label);
			SubcategoryTab captured = tab;
			((UnityEvent)val.onClick).AddListener((UnityAction)delegate
			{
				SelectSubcategory(captured);
			});
			m_subcategoryObjects.Add(((Component)val).gameObject);
			m_subcategoryTabs.Add(captured);
		}

		private void BuildGrid(RectTransform root)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: 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_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0216: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0259: Unknown result type (might be due to invalid IL or missing references)
			//IL_0283: Unknown result type (might be due to invalid IL or missing references)
			//IL_0289: Expected O, but got Unknown
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b2: 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_02d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_034c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0363: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = UiFactory.CreateRect("SearchRow", (Transform)(object)root);
			UiFactory.Anchor(val, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(14f, -116f), new Vector2(1124f, 34f));
			val.anchorMax = new Vector2(1f, 1f);
			val.sizeDelta = new Vector2(val.sizeDelta.x - 340f - 8f, 34f);
			val.offsetMin = new Vector2(14f, val.offsetMin.y);
			val.offsetMax = new Vector2(-362f, val.offsetMax.y);
			Image obj = ((Component)val).gameObject.AddComponent<Image>();
			obj.sprite = m_sprites.Slot;
			((Graphic)obj).color = new Color(0.1f, 0.1f, 0.12f, 0.95f);
			obj.type = (Type)1;
			m_searchLabel = UiFactory.CreateText("Query", (Transform)(object)val, 16f, new Color(0.92f, 0.9f, 0.82f), (TextAlignmentOptions)513);
			UiFactory.Stretch(((TMP_Text)m_searchLabel).rectTransform, 10f, 4f);
			((TMP_Text)m_searchLabel).rectTransform.offsetMax = new Vector2(-96f, -4f);
			m_countLabel = UiFactory.CreateText("Count", (Transform)(object)val, 14f, new Color(0.68f, 0.66f, 0.6f), (TextAlignmentOptions)516);
			((Graphic)m_countLabel).raycastTarget = false;
			((TMP_Text)m_countLabel).rectTransform.anchorMin = new Vector2(1f, 0f);
			((TMP_Text)m_countLabel).rectTransform.anchorMax = new Vector2(1f, 1f);
			((TMP_Text)m_countLabel).rectTransform.pivot = new Vector2(1f, 0.5f);
			((TMP_Text)m_countLabel).rectTransform.sizeDelta = new Vector2(86f, 0f);
			((TMP_Text)m_countLabel).rectTransform.anchoredPosition = new Vector2(-10f, 0f);
			((TMP_Text)m_countLabel).margin = new Vector4(0f, 0f, 0f, 0f);
			((TMP_Text)m_countLabel).textWrappingMode = (TextWrappingModes)0;
			RectTransform content;
			ScrollRect val2 = UiFactory.CreateScrollView("Grid", (Transform)(object)root, out content);
			RectTransform val3 = (RectTransform)((Component)val2).transform;
			UiFactory.Anchor(val3, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(14f, -150f), new Vector2(1124f, 0f));
			val3.anchorMin = new Vector2(0f, 0f);
			val3.anchorMax = new Vector2(1f, 1f);
			val3.pivot = new Vector2(0.5f, 0.5f);
			val3.offsetMin = new Vector2(14f, 74f);
			val3.offsetMax = new Vector2(-362f, -150f);
			GridLayoutGroup obj2 = ((Component)content).gameObject.AddComponent<GridLayoutGroup>();
			obj2.cellSize = new Vector2((float)_cardSize, (float)_cardSize);
			obj2.spacing = new Vector2((float)_cardPadding, (float)_cardPadding);
			obj2.constraint = (Constraint)1;
			obj2.constraintCount = GridColumns();
			((LayoutGroup)obj2).childAlignment = (TextAnchor)0;
			((Component)content).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
			m_grid = val3;
			m_gridScroll = val2;
			m_gridContent = content;
			for (int i = 0; i < MaxItemsPerPage(); i++)
			{
				Card card = BuildCard(content);
				LayoutCard(card);
				m_cards.Add(card);
			}
			BuildPager(root);
		}

		private void BuildPager(RectTransform root)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0106: Unknown result type (might be due to invalid IL or missing references)
			//IL_0110: Expected O, but got Unknown
			//IL_0132: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Expected O, but got Unknown
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: 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_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Expected O, but got Unknown
			//IL_020f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Expected O, but got Unknown
			RectTransform val = UiFactory.CreateRect("Pager", (Transform)(object)root);
			UiFactory.Anchor(val, new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(14f, 40f), new Vector2(1124f, 30f));
			val.anchorMax = new Vector2(1f, 0f);
			val.offsetMin = new Vector2(14f, 40f);
			val.offsetMax = new Vector2(-362f, 70f);
			val.sizeDelta = new Vector2(val.sizeDelta.x, 30f);
			m_prevButton = UiFactory.CreateButton("Prev", (Transform)(object)val, m_sprites.Button, 14f);
			UiFactory.Anchor((RectTransform)((Component)m_prevButton).transform, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), Vector2.zero, new Vector2(80f, 28f));
			SetLabel(m_prevButton, "Prev");
			((UnityEvent)m_prevButton.onClick).AddListener((UnityAction)delegate
			{
				ChangePage(-1);
			});
			m_pageLabel = UiFactory.CreateText("Page", (Transform)(object)val, 14f, new Color(0.8f, 0.78f, 0.7f), (TextAlignmentOptions)514);
			UiFactory.Stretch(((TMP_Text)m_pageLabel).rectTransform, 90f, 0f);
			m_nextButton = UiFactory.CreateButton("Next", (Transform)(object)val, m_sprites.Button, 14f);
			UiFactory.Anchor((RectTransform)((Component)m_nextButton).transform, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), Vector2.zero, new Vector2(80f, 28f));
			SetLabel(m_nextButton, "Next");
			((UnityEvent)m_nextButton.onClick).AddListener((UnityAction)delegate
			{
				ChangePage(1);
			});
		}

		private Card BuildCard(RectTransform parent)
		{
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: 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_00c5: 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_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: 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_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_026f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b8: Expected O, but got Unknown
			RectTransform val = UiFactory.CreateRect("Card", (Transform)(object)parent);
			Image val2 = ((Component)val).gameObject.AddComponent<Image>();
			val2.sprite = m_sprites.Slot;
			((Graphic)val2).color = new Color(0.15f, 0.15f, 0.17f, 0.95f);
			val2.type = (Type)1;
			Button val3 = ((Component)val).gameObject.AddComponent<Button>();
			((Selectable)val3).targetGraphic = (Graphic)(object)val2;
			ColorBlock colors = ((Selectable)val3).colors;
			((ColorBlock)(ref colors)).normalColor = Color.white;
			((ColorBlock)(ref colors)).highlightedColor = new Color(1.35f, 1.25f, 1f, 1f);
			((ColorBlock)(ref colors)).selectedColor = Color.white;
			((ColorBlock)(ref colors)).pressedColor = new Color(0.8f, 0.8f, 0.8f, 1f);
			((Selectable)val3).colors = colors;
			RectTransform obj = UiFactory.CreateRect("Icon", (Transform)(object)val);
			UiFactory.Anchor(obj, new Vector2(0.5f, 1f), new Vector2(0.5f, 1f), new Vector2(0f, -4f), new Vector2(52f, 52f));
			Image val4 = ((Component)obj).gameObject.AddComponent<Image>();
			val4.preserveAspect = true;
			((Graphic)val4).raycastTarget = false;
			TextMeshProUGUI val5 = UiFactory.CreateText("Label", (Transform)(object)val, 11f, new Color(0.86f, 0.84f, 0.78f), (TextAlignmentOptions)1026);
			UiFactory.Stretch(((TMP_Text)val5).rectTransform, 3f, 3f);
			((TMP_Text)val5).rectTransform.anchorMin = Vector2.zero;
			((TMP_Text)val5).rectTransform.anchorMax = Vector2.one;
			((TMP_Text)val5).rectTransform.offsetMin = new Vector2(3f, 3f);
			((TMP_Text)val5).rectTransform.offsetMax = new Vector2(-3f, -22f);
			((TMP_Text)val5).overflowMode = (TextOverflowModes)1;
			((TMP_Text)val5).textWrappingMode = (TextWrappingModes)0;
			Card card = new Card
			{
				Background = val2,
				Icon = val4,
				Label = val5,
				Button = val3
			};
			RectTransform obj2 = UiFactory.CreateRect("Selected", (Transform)(object)val);
			UiFactory.Stretch(obj2, 2f, 2f);
			((Transform)obj2).SetAsFirstSibling();
			Image val6 = ((Component)obj2).gameObject.AddComponent<Image>();
			val6.sprite = m_sprites.ButtonActive;
			val6.type = (Type)1;
			((Graphic)val6).color = new Color(1f, 0.92f, 0.7f, 0.45f);
			((Graphic)val6).raycastTarget = false;
			((Behaviour)val6).enabled = false;
			card.Selected = val6;
			LayoutCard(card);
			((UnityEvent)val3.onClick).AddListener((UnityAction)delegate
			{
				OnCardClicked(card);
			});
			return card;
		}

		private static void LayoutCard(Card card)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Clamp((float)_cardSize - 24f, 32f, 112f);
			((Graphic)card.Icon).rectTransform.sizeDelta = new Vector2(num, num);
		}

		private void BuildDetails(RectTransform root)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: 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_0083: 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_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0131: Unknown result type (might be due to invalid IL or missing references)
			//IL_0140: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)