Decompiled source of SpongePEAKCheats v1.0.0

plugins/com.sponge.peakcheats.dll

Decompiled 8 hours ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BepInEx;
using BepInEx.Configuration;
using Microsoft.CodeAnalysis;
using Photon.Pun;
using SpongePEAK.Cheats.Features;
using SpongePEAK.Cheats.Spawning;
using SpongePEAK.Cheats.UI;
using SpongePEAK.Core.Logging;
using SpongePEAK.Core.Patching;
using SpongePEAK.Lib.Features;
using SpongePEAK.Lib.Items;
using SpongePEAK.Lib.Plugin;
using SpongePEAK.Lib.UI;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using Zorro.Core;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("sponge")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright (c) sponge")]
[assembly: AssemblyDescription("Item spawner and testing tools. Off by default.")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+ddcbf023fcb4c2065ad9b038910633cd4a3a93b0")]
[assembly: AssemblyProduct("SpongePEAKCheats")]
[assembly: AssemblyTitle("com.sponge.peakcheats")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SpongePEAK.Cheats
{
	[BepInPlugin("com.sponge.peakcheats", "SpongePEAKCheats", "1.0.0")]
	public sealed class CheatsPlugin : SpongePlugin
	{
		public const string Guid = "com.sponge.peakcheats";

		private FeatureRegistry _registry;

		private ItemSpawnerFeature _spawner;

		protected override string DisplayName => "SpongePEAKCheats";

		protected override void OnLoad()
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Expected O, but got Unknown
			_registry = new FeatureRegistry(((BaseUnityPlugin)this).Config, ((SpongePlugin)this).Log);
			_spawner = new ItemSpawnerFeature();
			_spawner.Configure(((BaseUnityPlugin)this).Config);
			_registry.Register((ModFeature)(object)_spawner);
			_registry.EnableAll(((SpongePlugin)this).Patches);
		}

		private void Update()
		{
			if (_spawner != null && ((ModFeature)_spawner).IsActive)
			{
				_spawner.Tick();
			}
		}

		protected override void OnUnload()
		{
			_spawner?.Cleanup();
		}
	}
}
namespace SpongePEAK.Cheats.UI
{
	public sealed class SpawnerWindow
	{
		private readonly ItemSpawner _spawner;

		private readonly ModLog _log;

		private GameObject _root;

		private RectTransform _content;

		private ScrollRect _scroll;

		private TMP_InputField _search;

		private TextMeshProUGUI _status;

		private ModalCursorWindow _modal;

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

		private IReadOnlyList<SpawnableItem> _results = Array.Empty<SpawnableItem>();

		private string _lastQuery;

		public bool IsOpen { get; private set; }

		public SpawnerWindow(ItemSpawner spawner, ModLog log)
		{
			_spawner = spawner;
			_log = log;
		}

		public void Toggle()
		{
			if (IsOpen)
			{
				Close();
			}
			else if (!((Object)(object)_root == (Object)null) || Build())
			{
				IsOpen = true;
				_root.SetActive(true);
				Refilter(force: true);
				ApplyCursor();
				if ((Object)(object)_search != (Object)null)
				{
					_search.text = string.Empty;
					_search.ActivateInputField();
				}
			}
		}

		public void Close()
		{
			if (IsOpen)
			{
				IsOpen = false;
				if ((Object)(object)_root != (Object)null)
				{
					_root.SetActive(false);
				}
				ApplyCursor();
			}
		}

		public void Tick()
		{
			if (IsOpen && (Object)(object)_search != (Object)null && _search.text != _lastQuery)
			{
				Refilter();
			}
		}

		private bool Build()
		{
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Expected O, but got Unknown
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				_root = new GameObject("SpongeUI_Spawner", new Type[3]
				{
					typeof(Canvas),
					typeof(CanvasScaler),
					typeof(GraphicRaycaster)
				});
				Object.DontDestroyOnLoad((Object)(object)_root);
				Canvas component = _root.GetComponent<Canvas>();
				component.renderMode = (RenderMode)0;
				component.sortingOrder = 500;
				CanvasScaler component2 = _root.GetComponent<CanvasScaler>();
				component2.uiScaleMode = (ScaleMode)1;
				component2.referenceResolution = new Vector2(1920f, 1080f);
				component2.matchWidthOrHeight = 0.5f;
				RectTransform val = NewRect("Panel", _root.transform);
				val.anchorMin = new Vector2(0.5f, 0.5f);
				val.anchorMax = new Vector2(0.5f, 0.5f);
				val.pivot = new Vector2(0.5f, 0.5f);
				val.sizeDelta = new Vector2(620f, 760f);
				val.anchoredPosition = Vector2.zero;
				((Graphic)((Component)val).gameObject.AddComponent<Image>()).color = new Color(0.13f, 0.1f, 0.07f, 0.96f);
				AddTitle(val);
				AddSearch(val);
				AddList(val);
				AddFooter(val);
				_modal = _root.AddComponent<ModalCursorWindow>();
				_modal.SetLogger(_log);
				_modal.Closed = delegate
				{
					IsOpen = false;
					if ((Object)(object)_root != (Object)null)
					{
						_root.SetActive(false);
					}
				};
				_root.SetActive(false);
				return true;
			}
			catch (Exception ex)
			{
				ModLog log = _log;
				if (log != null)
				{
					log.Exception("Could not build the spawner window", ex);
				}
				_root = null;
				return false;
			}
		}

		private void AddTitle(RectTransform panel)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			RectTransform obj = NewRect("Title", (Transform)(object)panel);
			obj.anchorMin = new Vector2(0f, 1f);
			obj.anchorMax = new Vector2(1f, 1f);
			obj.pivot = new Vector2(0.5f, 1f);
			obj.sizeDelta = new Vector2(-40f, 44f);
			obj.anchoredPosition = new Vector2(0f, -14f);
			TextMeshProUGUI obj2 = ((Component)obj).gameObject.AddComponent<TextMeshProUGUI>();
			((TMP_Text)obj2).text = "ITEM SPAWNER";
			((TMP_Text)obj2).fontSize = 28f;
			((TMP_Text)obj2).alignment = (TextAlignmentOptions)514;
			((Graphic)obj2).color = new Color(0.98f, 0.86f, 0.55f);
			Inherit(obj2);
		}

		private void AddSearch(RectTransform panel)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0176: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = NewRect("Search", (Transform)(object)panel);
			val.anchorMin = new Vector2(0f, 1f);
			val.anchorMax = new Vector2(1f, 1f);
			val.pivot = new Vector2(0.5f, 1f);
			val.sizeDelta = new Vector2(-48f, 46f);
			val.anchoredPosition = new Vector2(0f, -66f);
			((Graphic)((Component)val).gameObject.AddComponent<Image>()).color = new Color(0.05f, 0.04f, 0.03f, 0.95f);
			RectTransform val2 = NewRect("TextArea", (Transform)(object)val, typeof(RectMask2D));
			Fill(val2, 10f);
			RectTransform obj = NewRect("Text", (Transform)(object)val2);
			Fill(obj, 0f);
			TextMeshProUGUI val3 = ((Component)obj).gameObject.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val3).fontSize = 20f;
			((TMP_Text)val3).alignment = (TextAlignmentOptions)4097;
			((Graphic)val3).color = Color.white;
			Inherit(val3);
			RectTransform obj2 = NewRect("Placeholder", (Transform)(object)val2);
			Fill(obj2, 0f);
			TextMeshProUGUI val4 = ((Component)obj2).gameObject.AddComponent<TextMeshProUGUI>();
			((TMP_Text)val4).text = "Search items...";
			((TMP_Text)val4).fontSize = 20f;
			((TMP_Text)val4).alignment = (TextAlignmentOptions)4097;
			((Graphic)val4).color = new Color(1f, 1f, 1f, 0.35f);
			Inherit(val4);
			_search = ((Component)val).gameObject.AddComponent<TMP_InputField>();
			_search.textViewport = val2;
			_search.textComponent = (TMP_Text)(object)val3;
			_search.placeholder = (Graphic)(object)val4;
			_search.caretColor = Color.white;
		}

		private void AddList(RectTransform panel)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			RectTransform val = NewRect("List", (Transform)(object)panel);
			val.anchorMin = new Vector2(0f, 0f);
			val.anchorMax = new Vector2(1f, 1f);
			val.offsetMin = new Vector2(24f, 64f);
			val.offsetMax = new Vector2(-24f, -122f);
			_content = val;
			_scroll = ScrollableList.Ensure((Transform)(object)_content, _log, 3f);
		}

		private void AddFooter(RectTransform panel)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: 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_0120: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			//IL_014a: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = NewRect("Status", (Transform)(object)panel);
			val.anchorMin = new Vector2(0f, 0f);
			val.anchorMax = new Vector2(1f, 0f);
			val.pivot = new Vector2(0.5f, 0f);
			val.sizeDelta = new Vector2(-40f, 28f);
			val.anchoredPosition = new Vector2(0f, 30f);
			_status = ((Component)val).gameObject.AddComponent<TextMeshProUGUI>();
			((TMP_Text)_status).fontSize = 16f;
			((TMP_Text)_status).alignment = (TextAlignmentOptions)514;
			((Graphic)_status).color = new Color(1f, 1f, 1f, 0.5f);
			Inherit(_status);
			RectTransform val2 = NewRect("Close", (Transform)(object)panel);
			val2.anchorMin = new Vector2(1f, 0f);
			val2.anchorMax = new Vector2(1f, 0f);
			val2.pivot = new Vector2(1f, 0f);
			val2.sizeDelta = new Vector2(120f, 34f);
			val2.anchoredPosition = new Vector2(-24f, -2f);
			PeakStyle.CreateButton("CLOSE", (Transform)(object)val2, (Action)Close);
		}

		private void Refilter(bool force = false)
		{
			string text = (((Object)(object)_search != (Object)null) ? _search.text : string.Empty);
			if (!force && text == _lastQuery)
			{
				return;
			}
			_lastQuery = text;
			_results = _spawner.Search(text);
			for (int i = 0; i < _results.Count; i++)
			{
				GameObject val = ((i < _rows.Count) ? _rows[i] : CreateRow());
				if (!((Object)(object)val == (Object)null))
				{
					int index = i;
					SpawnableItem item = _results[i];
					val.SetActive(true);
					SetRowLabel(val, item);
					Rebind(val, delegate
					{
						OnSpawn(index);
					});
				}
			}
			for (int num = _results.Count; num < _rows.Count; num++)
			{
				_rows[num].SetActive(false);
			}
			UpdateStatus();
			ScrollableList.Refresh(_scroll);
		}

		private GameObject CreateRow()
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				RectTransform val = NewRect($"Row{_rows.Count}", (Transform)(object)_content);
				val.sizeDelta = new Vector2(0f, 34f);
				LayoutElement obj = ((Component)val).gameObject.AddComponent<LayoutElement>();
				obj.preferredHeight = 34f;
				obj.minHeight = 34f;
				Button val2 = PeakStyle.CreateButton("item", (Transform)(object)val, (Action)null);
				if ((Object)(object)val2 != (Object)null)
				{
					RectTransform component = ((Component)val2).GetComponent<RectTransform>();
					if ((Object)(object)component != (Object)null)
					{
						Fill(component, 0f);
					}
				}
				_rows.Add(((Component)val).gameObject);
				return ((Component)val).gameObject;
			}
			catch (Exception ex)
			{
				ModLog log = _log;
				if (log != null)
				{
					log.Exception("Could not create a spawner row", ex);
				}
				return null;
			}
		}

		private static void SetRowLabel(GameObject row, SpawnableItem item)
		{
			TextMeshProUGUI componentInChildren = row.GetComponentInChildren<TextMeshProUGUI>(true);
			if (!((Object)(object)componentInChildren == (Object)null))
			{
				((TMP_Text)componentInChildren).text = (item.DisplayName.Equals(item.PrefabName, StringComparison.OrdinalIgnoreCase) ? item.DisplayName : (item.DisplayName + "   <color=#FFFFFF60>" + item.PrefabName + "</color>"));
				((TMP_Text)componentInChildren).alignment = (TextAlignmentOptions)4097;
				((TMP_Text)componentInChildren).fontSize = 17f;
			}
		}

		private static void Rebind(GameObject row, Action onClick)
		{
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: Expected O, but got Unknown
			Button componentInChildren = row.GetComponentInChildren<Button>(true);
			if (!((Object)(object)componentInChildren == (Object)null))
			{
				((UnityEventBase)componentInChildren.onClick).RemoveAllListeners();
				((UnityEvent)componentInChildren.onClick).AddListener((UnityAction)delegate
				{
					onClick();
				});
			}
		}

		private void OnSpawn(int index)
		{
			if (index >= 0 && index < _results.Count)
			{
				SpawnableItem spawnableItem = _results[index];
				if (!_spawner.IsAvailable)
				{
					SetStatus("Cannot spawn right now: not in a run.");
				}
				else
				{
					SetStatus(_spawner.Spawn(spawnableItem.PrefabName) ? ("Spawned " + spawnableItem.DisplayName) : ("Failed to spawn " + spawnableItem.DisplayName));
				}
			}
		}

		private void UpdateStatus()
		{
			if ((Object)(object)_status == (Object)null)
			{
				return;
			}
			int count = _spawner.All().Count;
			if (count == 0)
			{
				SetStatus("No items found. Start a run first; the database loads with the level.");
				return;
			}
			if (_results.Count == 0)
			{
				SetStatus($"Nothing matches that. {count} items available.");
				return;
			}
			int count2 = ItemCloner.BuiltItems.Count;
			int pendingCount = ItemCloner.PendingCount;
			if (count2 > 0)
			{
				SetStatus($"{_results.Count} of {count} items  ({count2} custom)");
			}
			else if (pendingCount > 0)
			{
				SetStatus($"{_results.Count} of {count} items  ({pendingCount} custom registered but not built yet)");
			}
			else
			{
				SetStatus($"{_results.Count} of {count} items  (no custom items registered)");
			}
		}

		private void SetStatus(string message)
		{
			if ((Object)(object)_status != (Object)null)
			{
				((TMP_Text)_status).text = message;
			}
		}

		private void ApplyCursor()
		{
			ModalCursorWindow modal = _modal;
			if (modal != null)
			{
				modal.SetOpen(IsOpen);
			}
		}

		private static RectTransform NewRect(string name, Transform parent, params Type[] extra)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			List<Type> list = new List<Type> { typeof(RectTransform) };
			list.AddRange(extra);
			RectTransform component = new GameObject(name, list.ToArray()).GetComponent<RectTransform>();
			((Transform)component).SetParent(parent, false);
			return component;
		}

		private static void Fill(RectTransform rect, float padding)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			rect.anchorMin = Vector2.zero;
			rect.anchorMax = Vector2.one;
			rect.offsetMin = new Vector2(padding, padding);
			rect.offsetMax = new Vector2(0f - padding, 0f - padding);
		}

		private static void Inherit(TextMeshProUGUI text)
		{
			GameObject buttonTemplate = PeakStyle.ButtonTemplate;
			if (!((Object)(object)buttonTemplate == (Object)null))
			{
				TextMeshProUGUI componentInChildren = buttonTemplate.GetComponentInChildren<TextMeshProUGUI>(true);
				if ((Object)(object)((componentInChildren != null) ? ((TMP_Text)componentInChildren).font : null) != (Object)null)
				{
					((TMP_Text)text).font = ((TMP_Text)componentInChildren).font;
				}
			}
		}
	}
}
namespace SpongePEAK.Cheats.Spawning
{
	public sealed class ItemSpawner
	{
		private readonly ModLog _log;

		private static readonly MethodInfo SpawnInHand = typeof(CharacterItems).GetMethod("SpawnItemInHand", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, new Type[1] { typeof(string) }, null);

		public bool IsAvailable
		{
			get
			{
				if (SpawnInHand != null && (Object)(object)Character.localCharacter != (Object)null)
				{
					return PhotonNetwork.InRoom;
				}
				return false;
			}
		}

		public ItemSpawner(ModLog log)
		{
			_log = log;
		}

		public IReadOnlyList<SpawnableItem> All()
		{
			ItemDatabase instance = SingletonAsset<ItemDatabase>.Instance;
			if (instance?.itemLookup == null)
			{
				return Array.Empty<SpawnableItem>();
			}
			return (from item in instance.itemLookup.Values
				where (Object)(object)item != (Object)null
				select new SpawnableItem(((Object)item).name, item.UIData?.itemName ?? ((Object)item).name, item.itemID)).OrderBy<SpawnableItem, string>((SpawnableItem entry) => entry.DisplayName, StringComparer.OrdinalIgnoreCase).ThenBy<SpawnableItem, string>((SpawnableItem entry) => entry.PrefabName, StringComparer.OrdinalIgnoreCase).ToList();
		}

		public IReadOnlyList<SpawnableItem> Search(string query)
		{
			IReadOnlyList<SpawnableItem> readOnlyList = All();
			if (string.IsNullOrWhiteSpace(query))
			{
				return readOnlyList;
			}
			return readOnlyList.Where((SpawnableItem entry) => entry.DisplayName.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0 || entry.PrefabName.IndexOf(query, StringComparison.OrdinalIgnoreCase) >= 0).ToList();
		}

		public bool Spawn(string prefabName)
		{
			if (string.IsNullOrWhiteSpace(prefabName))
			{
				return false;
			}
			if (SpawnInHand == null)
			{
				ModLog log = _log;
				if (log != null)
				{
					log.Warning((object)"CharacterItems.SpawnItemInHand not found; the game may have changed.");
				}
				return false;
			}
			Character localCharacter = Character.localCharacter;
			if ((Object)(object)localCharacter == (Object)null || (Object)(object)localCharacter.refs?.items == (Object)null)
			{
				ModLog log2 = _log;
				if (log2 != null)
				{
					log2.Warning((object)"Cannot spawn: no local character.");
				}
				return false;
			}
			if (!PhotonNetwork.InRoom)
			{
				ModLog log3 = _log;
				if (log3 != null)
				{
					log3.Warning((object)"Cannot spawn: not in a room.");
				}
				return false;
			}
			try
			{
				SpawnInHand.Invoke(localCharacter.refs.items, new object[1] { prefabName });
				ModLog log4 = _log;
				if (log4 != null)
				{
					log4.Info((object)("Spawned '" + prefabName + "'."));
				}
				return true;
			}
			catch (Exception ex)
			{
				ModLog log5 = _log;
				if (log5 != null)
				{
					log5.Exception("Failed to spawn '" + prefabName + "'", ex);
				}
				return false;
			}
		}
	}
	public readonly struct SpawnableItem
	{
		public string PrefabName { get; }

		public string DisplayName { get; }

		public ushort Id { get; }

		public SpawnableItem(string prefabName, string displayName, ushort id)
		{
			PrefabName = prefabName;
			DisplayName = displayName;
			Id = id;
		}
	}
}
namespace SpongePEAK.Cheats.Features
{
	public sealed class ItemSpawnerFeature : ModFeature
	{
		private ConfigEntry<KeyCode> _hotkey;

		private SpawnerWindow _window;

		private ModLog _log;

		public override string Name => "ItemSpawner";

		public override string Description => "Opens a searchable list of every item, vanilla and custom, and spawns them into your hands.";

		public override string Replaces => "ItemSpawnerEnhanced";

		public override bool DefaultEnabled => true;

		public override string Section => "Cheats";

		public void Configure(ConfigFile config)
		{
			_hotkey = config.Bind<KeyCode>("Cheats", "SpawnerHotkey", (KeyCode)284, "Key that opens the item spawner.");
		}

		protected override void OnEnable(PatchHost patches, ModLog log)
		{
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			_log = log;
			_window = new SpawnerWindow(new ItemSpawner(log), log);
			ConfigEntry<KeyCode> hotkey = _hotkey;
			log.Info((object)$"Item spawner ready; press {(object)(KeyCode)((hotkey == null) ? 284 : ((int)hotkey.Value))} to open it.");
		}

		public void Tick()
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (_window != null)
			{
				ConfigEntry<KeyCode> hotkey = _hotkey;
				if (Input.GetKeyDown((KeyCode)((hotkey == null) ? 284 : ((int)hotkey.Value))))
				{
					_window.Toggle();
				}
				_window.Tick();
			}
		}

		public void Cleanup()
		{
			_window?.Close();
		}
	}
}