Decompiled source of Hearthforge v1.0.5

plugins/Hearthforge.dll

Decompiled 9 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Hearthforge.Core;
using Hearthforge.Modules;
using Hearthforge.Modules.Hud;
using Hearthforge.UI;
using Microsoft.CodeAnalysis;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.Audio;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.InputSystem;
using UnityEngine.InputSystem.Utilities;
using UnityEngine.Rendering;
using UnityEngine.SceneManagement;
using UnityEngine.TextCore.LowLevel;
using UnityEngine.UI;

[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("Hearthforge")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.158.0")]
[assembly: AssemblyInformationalVersion("1.1.158+0f16abd-dirty.202610221603")]
[assembly: AssemblyProduct("Hearthforge")]
[assembly: AssemblyTitle("Hearthforge")]
[assembly: AssemblyMetadata("AI_Assisted_Creation", "This assembly was partially created with the assistance of Generative AI (code and documentation), reviewed and tested by the author.")]
[assembly: AssemblyMetadata("AI_Model_Vendor", "Grok Bot")]
[assembly: AssemblyVersion("1.1.158.0")]
[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 Hearthforge
{
	[BepInPlugin("spencer.hearthforge", "Hearthforge", "1.1.159")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "spencer.hearthforge";

		public const string ModName = "Hearthforge";

		public const string Version = "1.1.159";

		internal static ManualLogSource Log;

		private Harmony coreHarmony;

		public static Plugin Instance { get; private set; }

		public ModuleManager Modules { get; private set; }

		private void Awake()
		{
			//IL_0346: Unknown result type (might be due to invalid IL or missing references)
			//IL_0350: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			LogBuild();
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = true;
			Options.Init(((BaseUnityPlugin)this).Config);
			SettingsPanel.BindOptions();
			ConfigSync.BindOptions();
			Modules = new ModuleManager(((BaseUnityPlugin)this).Logger);
			Modules.Register<HaulingSkillModule>();
			Modules.Register<SwimTweaksModule>();
			Modules.Register<SkipIntroModule>();
			Modules.Register<RestingModule>();
			Modules.Register<LootingModule>();
			Modules.Register<AxeComboModule>();
			Modules.Register<TeleportModule>();
			Modules.Register<PlantingModule>();
			Modules.Register<ExplorationModule>();
			Modules.Register<HearthModule>();
			Modules.Register<BackpackModule>();
			Modules.Register<QuartermasterModule>();
			Modules.Register<SocialModule>();
			Modules.Register<DeathPenaltyModule>();
			Modules.Register<TraderStallModule>();
			Modules.Register<DvergrBuildModule>();
			Modules.Register<MapStyleModule>();
			Modules.Register<BushPlantingModule>();
			Modules.Register<RuneforgeModule>();
			Modules.Register<TabTargetModule>();
			Modules.Register<PlantEverythingModule>();
			Modules.Register<AchievementsModule>();
			Modules.Register<DevCommandsModule>();
			Modules.Register<ZoneResetModule>();
			Modules.Register<WardGuardModule>();
			Modules.Register<WaterModule>();
			Modules.Register<EquipmentPanelModule>();
			Modules.Register<InfiniteFuelModule>();
			Modules.Register<CaveFogModule>();
			Modules.Register<CameraModule>();
			Modules.Register<MeadowsAnywhereModule>();
			Modules.Register<WispColumnModule>();
			Modules.Register<BulkLoadModule>();
			Modules.Register<StorageModule>();
			Modules.Register<ApiaryModule>();
			Modules.Register<CoinPurseModule>();
			Modules.Register<GraveyardModule>();
			Modules.Register<SmelteryModule>();
			Modules.Register<ProspectorModule>();
			Modules.Register<OfflineProgressModule>();
			Modules.Register<FermenterModule>();
			Modules.Register<YggdrasilRootModule>();
			Modules.Register<ShipStyleModule>();
			Modules.Register<WishboneModule>();
			Modules.Register<GildedUIModule>();
			Modules.Register<HomesteadModule>();
			Modules.Register<SignStyleModule>();
			Modules.Register<WellFedModule>();
			Modules.Register<BossStonesModule>();
			Modules.Register<AdminAreaCopyModule>();
			Modules.Register<TerrainToolsModule>();
			Modules.Register<GraphicsModule>();
			Modules.Register<StationScaleModule>();
			Modules.Register<ShipSalvageModule>();
			Modules.Register<SailingModule>();
			Modules.Register<SlopeAssistModule>();
			Modules.Register<BuildInteractModule>();
			Modules.Register<TrailsModule>();
			Modules.Register<LongshipHarborModule>();
			Modules.Register<TamerModule>();
			Modules.Register<DyeModule>();
			Modules.Register<HudModule>();
			Modules.Register<SeedPreviewModule>();
			Modules.Register<TerrainEditCapModule>();
			Modules.Register<EquippedHighlightModule>();
			Modules.Register<DayNightModule>();
			Modules.Register<ArmorStandSwapModule>();
			Modules.Register<WorldRenewModule>();
			Modules.InitAll();
			coreHarmony = new Harmony("spencer.hearthforge.core");
			Type[] array = new Type[15]
			{
				typeof(ConfigSync.Hooks),
				typeof(Staff.Hooks),
				typeof(InputBlock),
				typeof(StartupGuard),
				typeof(PieceKit.Hooks),
				typeof(UnlockMsgGuard),
				typeof(RecipeGuard),
				typeof(ContainerRpcFix),
				typeof(DevCommands),
				typeof(LegacyCleanup),
				typeof(BagGuard),
				typeof(KilnGuard),
				typeof(PieceTags.Patches),
				typeof(OfflineProgressModule.Patches),
				typeof(VoxheimSafety.Patches)
			};
			foreach (Type type in array)
			{
				try
				{
					coreHarmony.CreateClassProcessor(type).Patch();
				}
				catch (Exception arg)
				{
					((BaseUnityPlugin)this).Logger.LogError((object)$"Core patch {type.Name} failed and was skipped: {arg}");
				}
			}
			InstanceReport.On = Options.Bind("Debug", "InstanceReport", def: false, "Every minute, log networked instance counts (top prefabs and all Hearthforge objects)", synced: false);
			((Component)this).gameObject.AddComponent<InstanceReport>();
			FxSweeper.On = Options.Bind("Debug", "FxSweeper", def: false, "FX Sweeper log: also log vanilla and other mods' odd-looking effects (debug only). Broken Hearthforge effects are always switched off. Console: hf_fx", synced: false);
			ModOption<bool> modOption = Options.Bind("Debug", "DebugLogsOff1161", def: false, "Internal: debug logs default migrated to off", synced: false);
			if (!modOption.Value)
			{
				FxSweeper.On.Value = false;
				InstanceReport.On.Value = false;
				modOption.Value = true;
			}
			((Component)this).gameObject.AddComponent<FxSweeper>();
			PerfMonitor.Overlay = Options.Bind("Debug", "PerfOverlay", def: false, "Perf overlay: per-module ms/frame, calls and KB allocated per frame (only measured while on; off = zero cost). Console: hf_perf [seconds] dumps to the log", synced: false);
			PerfMonitor.Profiler = Options.Bind("Debug", "Profiler", def: false, "Profiler: once a minute, log the 10 most expensive Hearthforge patches and updates of that minute (times every Hearthforge method only while on; off = zero cost)", synced: false);
			((Component)this).gameObject.AddComponent<PerfMonitor>();
			try
			{
				((Component)this).gameObject.AddComponent<SettingsPanel>();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)("Settings panel failed: " + ex));
			}
			PurgeOrphanedConfig();
			((BaseUnityPlugin)this).Logger.LogMessage((object)string.Format("===== {0} {1} loaded ({2} modules, {3} options) =====", "Hearthforge", "1.1.159", Modules.List.Count, Options.All.Count));
			try
			{
				HashSet<string> vis = new HashSet<string> { "Graphics", "CaveFog", "Camera", "SwimTweaks", "WispColumn" };
				List<string> list = (from o in Options.All
					where vis.Contains(o.Module) && !object.Equals(o.Boxed, o.DefaultBoxed)
					select $"{o.Module}.{o.Key}={o.Boxed}").ToList();
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[Visuals] non-default settings: " + ((list.Count == 0) ? "none (all vanilla defaults)" : string.Join(", ", list))));
			}
			catch (Exception ex2)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[Visuals] settings dump failed: " + ex2.Message));
			}
		}

		private void PurgeOrphanedConfig()
		{
			try
			{
				if (!(AccessTools.Property(typeof(ConfigFile), "OrphanedEntries")?.GetValue(((BaseUnityPlugin)this).Config) is Dictionary<ConfigDefinition, string> { Count: not 0 } dictionary))
				{
					return;
				}
				List<ConfigDefinition> list = dictionary.Keys.Where((ConfigDefinition d) => !d.Section.StartsWith("Knarr", StringComparison.Ordinal)).ToList();
				if (list.Count == 0)
				{
					return;
				}
				foreach (ConfigDefinition item in list)
				{
					dictionary.Remove(item);
				}
				int count = list.Count;
				((BaseUnityPlugin)this).Config.Save();
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"Removed {count} obsolete setting(s) from the config file.");
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Config cleanup skipped: " + ex.Message));
			}
		}

		private void LogBuild()
		{
			Assembly assembly = typeof(Plugin).Assembly;
			AssemblyInformationalVersionAttribute assemblyInformationalVersionAttribute = (AssemblyInformationalVersionAttribute)Attribute.GetCustomAttribute(assembly, typeof(AssemblyInformationalVersionAttribute));
			string location = assembly.Location;
			string text = (File.Exists(location) ? File.GetLastWriteTime(location).ToString("yyyy-MM-dd HH:mm:ss") : "?");
			((BaseUnityPlugin)this).Logger.LogMessage((object)("Hearthforge build " + (assemblyInformationalVersionAttribute?.InformationalVersion ?? "1.1.159") + " | " + location + " | file time " + text));
			try
			{
				string[] files = Directory.GetFiles(Paths.PluginPath, "Hearthforge*.dll", SearchOption.AllDirectories);
				foreach (string text2 in files)
				{
					if (!string.Equals(Path.GetFullPath(text2), Path.GetFullPath(location), StringComparison.OrdinalIgnoreCase))
					{
						((BaseUnityPlugin)this).Logger.LogWarning((object)("Another Hearthforge DLL is installed and may be loaded instead of this one: " + text2));
					}
				}
			}
			catch
			{
			}
		}

		private void OnDestroy()
		{
			Harmony obj = coreHarmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			Modules?.DisableAll();
		}
	}
}
namespace Hearthforge.UI
{
	public static class ConfirmDialog
	{
		private class Keys : MonoBehaviour
		{
			private void Update()
			{
				if (Widgets.KeyDown((KeyCode)27))
				{
					SettingsPanel.SwallowEscapeFrame = Time.frameCount;
					Close(ok: false);
				}
				else if ((Object)(object)Player.m_localPlayer == (Object)null)
				{
					Close(ok: false);
				}
			}
		}

		private static GameObject root;

		private static TextMeshProUGUI title;

		private static TextMeshProUGUI text;

		private static TextMeshProUGUI yesLabel;

		private static Action yes;

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

		public static void Ask(string heading, string body, string yesText, Action onYes)
		{
			if ((Object)(object)root == (Object)null)
			{
				Build();
			}
			yes = onYes;
			((TMP_Text)title).text = heading;
			((TMP_Text)text).text = body;
			((TMP_Text)yesLabel).text = yesText;
			root.SetActive(true);
			root.transform.SetAsLastSibling();
			UiFocus.Grab();
		}

		private static void Close(bool ok)
		{
			if ((Object)(object)root != (Object)null)
			{
				root.SetActive(false);
			}
			Action action = yes;
			yes = null;
			if (ok)
			{
				try
				{
					action?.Invoke();
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("[UI] confirm action failed: " + ex.Message));
				}
			}
		}

		private static void Build()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: 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_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_01bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0207: 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_0225: Unknown result type (might be due to invalid IL or missing references)
			//IL_0234: Unknown result type (might be due to invalid IL or missing references)
			//IL_028d: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ba: Unknown result type (might be due to invalid IL or missing references)
			root = new GameObject("HF_Confirm", new Type[4]
			{
				typeof(RectTransform),
				typeof(Canvas),
				typeof(CanvasScaler),
				typeof(GraphicRaycaster)
			});
			Object.DontDestroyOnLoad((Object)(object)root);
			Canvas component = root.GetComponent<Canvas>();
			component.renderMode = (RenderMode)0;
			component.sortingOrder = 30025;
			CanvasScaler component2 = root.GetComponent<CanvasScaler>();
			component2.uiScaleMode = (ScaleMode)1;
			component2.referenceResolution = new Vector2(1920f, 1080f);
			component2.matchWidthOrHeight = 0.5f;
			HfCanvas.Register(component2);
			RectTransform val = Theme.Rect("Window", root.transform);
			Theme.Place(val, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(600f, 290f));
			Gilded.WindowBg(val);
			RectTransform obj = Theme.Rect("Title", (Transform)(object)val, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(10f, -58f), new Vector2(-10f, -10f));
			Theme.TitleBarImg((Component)(object)obj);
			((Component)obj).gameObject.AddComponent<Draggable>().Target = val;
			title = Theme.Label((Transform)(object)obj, "", 24f, Theme.Gold, (TextAlignmentOptions)513, header: true);
			((TMP_Text)title).rectTransform.offsetMin = new Vector2(16f, 0f);
			text = Theme.Label((Transform)(object)Theme.Rect("Body", (Transform)(object)val, Vector2.zero, Vector2.one, new Vector2(24f, 76f), new Vector2(-24f, -68f)), "", 17f, Theme.Text, (TextAlignmentOptions)514);
			((TMP_Text)text).textWrappingMode = (TextWrappingModes)1;
			RectTransform obj2 = Theme.Rect("Yes", (Transform)(object)val);
			Theme.Place(obj2, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(-95f, 20f), new Vector2(170f, 42f));
			yesLabel = ((Component)Widgets.Button((Transform)(object)obj2, "Yes", delegate
			{
				Close(ok: true);
			}, 17f)).GetComponentInChildren<TextMeshProUGUI>();
			RectTransform obj3 = Theme.Rect("No", (Transform)(object)val);
			Theme.Place(obj3, new Vector2(0.5f, 0f), new Vector2(0.5f, 0f), new Vector2(95f, 20f), new Vector2(170f, 42f));
			Widgets.Button((Transform)(object)obj3, "Cancel", delegate
			{
				Close(ok: false);
			}, 17f);
			root.AddComponent<Keys>();
			root.SetActive(false);
		}
	}
	public static class F7Catalog
	{
		public struct Spot
		{
			public string Page;

			public string Section;

			public bool Advanced;
		}

		public const string HUD = "HUD";

		public const string Frames = "Frames";

		public const string Other = "Other Mods";

		public const string Misc = "Miscellaneous";

		public const string Admin = "Admin";

		public const string AdminSettings = "AdminSettings";

		public const string StaffPage = "Staff";

		public static readonly string[] Categories;

		private static readonly Dictionary<string, string> cat;

		private static readonly Dictionary<string, string> parent;

		private static readonly Dictionary<string, string> section;

		private static readonly Dictionary<string, string> keySection;

		private static readonly Dictionary<string, string> toFrames;

		private static readonly HashSet<string> hudFrameKeys;

		private static readonly Dictionary<string, string> subtitle;

		private static readonly HashSet<string> advanced;

		private static readonly Regex advKey;

		private static readonly HashSet<(string, string)> internalKeys;

		private static int adminFrame;

		private static bool adminView;

		public static bool AdminView
		{
			get
			{
				int frameCount = Time.frameCount;
				if (frameCount != adminFrame)
				{
					adminFrame = frameCount;
					adminView = Staff.LocalIsAdmin();
				}
				return adminView;
			}
		}

		public static bool StaffView
		{
			get
			{
				if ((Object)(object)ZNet.instance != (Object)null && !ZNet.IsSinglePlayer)
				{
					if (!AdminView)
					{
						return Staff.Me != Staff.Role.Player;
					}
					return true;
				}
				return false;
			}
		}

		public static IEnumerable<IOption> Visible => Options.All.Where((IOption o) => !Internal(o));

		private static void C(string c, params string[] pages)
		{
			foreach (string key in pages)
			{
				cat[key] = c;
			}
		}

		static F7Catalog()
		{
			Categories = new string[13]
			{
				"Performance", "Graphics", "HUD", "Frames", "World & Travel", "Building & Base", "Farming & Production", "Inventory & Storage", "Combat & Gear", "Social",
				"Server & Debug", "Admin", "Miscellaneous"
			};
			cat = new Dictionary<string, string>();
			parent = new Dictionary<string, string>
			{
				{ "Hearth", "Teleport" },
				{ "GreenhandBushes", "Planting" },
				{ "PlantEverything", "Planting" },
				{ "TerrainEditCap", "TerrainTools" },
				{ "UI", "GildedUI" },
				{ "Debug", "Server" },
				{ "WarbandHUD", "HUD" },
				{ "EquippedHighlight", "HUD" },
				{ "TabTarget", "HUD" }
			};
			section = new Dictionary<string, string>
			{
				{ "Hearth", "Hearthstone" },
				{ "GreenhandBushes", "Bushes" },
				{ "PlantEverything", "Wild Plants" },
				{ "TerrainEditCap", "Terrain Edit Limit" },
				{ "UI", "Settings Window (F7)" },
				{ "Debug", "Debugging" },
				{ "WarbandHUD", "General" },
				{ "EquippedHighlight", "Equipped Glow" },
				{ "TabTarget", "Targeting" }
			};
			keySection = new Dictionary<string, string>();
			toFrames = new Dictionary<string, string>
			{
				{ "WarbandHUD.UnlockFramesKey", "Unlock Frames" },
				{ "WarbandHUD.HideFramesWithInventory", "Unlock Frames" },
				{ "WarbandHUD.HideVanillaFrames", "Unlock Frames" },
				{ "EquipmentPanel.CharacterPanelScale", "Character Panel" },
				{ "EquipmentPanel.ShowStats", "Character Panel" },
				{ "EquipmentPanel.PanelOffsetX", "Character Panel" },
				{ "EquipmentPanel.PanelOffsetY", "Character Panel" },
				{ "UI.PanelX", "Settings Window (F7)" },
				{ "UI.PanelY", "Settings Window (F7)" },
				{ "UI.PanelScale", "Settings Window (F7)" },
				{ "HUD Bags.BagOffsetX", "Bag, Chest & Crafting Windows" },
				{ "HUD Bags.BagOffsetY", "Bag, Chest & Crafting Windows" },
				{ "HUD Bags.ChestOffsetX", "Bag, Chest & Crafting Windows" },
				{ "HUD Bags.ChestOffsetY", "Bag, Chest & Crafting Windows" },
				{ "HUD Bags.CraftOffsetX", "Bag, Chest & Crafting Windows" },
				{ "HUD Bags.CraftOffsetY", "Bag, Chest & Crafting Windows" },
				{ "HUD Bags.ResetWindowPositions", "Bag, Chest & Crafting Windows" }
			};
			hudFrameKeys = new HashSet<string> { "Scale", "PosX", "PosY" };
			subtitle = new Dictionary<string, string>
			{
				{ "HUD", "Every HUD piece in one place" },
				{ "Frames", "Positions and sizes of every frame and window" },
				{ "Teleport", "Portals, map travel, Hearthstone" },
				{ "Exploration", "Exploring and map fog" },
				{ "MapStyle", "Map look" },
				{ "Sailing", "Sailing and ships" },
				{ "LongshipHarbor", "Dock and store ships" },
				{ "SwimTweaks", "Swimming" },
				{ "Trails", "Paths you walk often" },
				{ "BossStones", "Boss altars" },
				{ "Wishbone", "Quieter Wishbone" },
				{ "AreaReset", "Reset world areas" },
				{ "SeedPreview", "World seed preview" },
				{ "MeadowsAnywhere", "Meadows plants anywhere" },
				{ "Water", "Rivers and water" },
				{ "WispColumn", "Wisp beacon in the sky" },
				{ "SkipIntro", "Faster start-up" },
				{ "HomesteadMove", "Move a whole base" },
				{ "DvergrBuild", "Dvergr building pieces" },
				{ "SlopeAssist", "Building on slopes" },
				{ "BuildInteract", "Use E while building" },
				{ "TerrainTools", "Hoe, pickaxe, terrain" },
				{ "SignStyle", "Sign text styling" },
				{ "WardGuard", "Keep mobs out, ward radius" },
				{ "YggdrasilRoot", "Sap roots (full and mini)" },
				{ "TraderStalls", "Place traders at home" },
				{ "Shipwright", "Ship looks" },
				{ "ShipSalvage", "Take ships apart with the hammer" },
				{ "StationScale", "Smaller smelting stations" },
				{ "Resting", "Rested buff, comfort" },
				{ "AxeCombo", "Chopping trees" },
				{ "Planting", "Crops, bushes, wild plants" },
				{ "Apiary", "Beehives and harvest" },
				{ "Brewmaster", "Fermenters, honey, queue" },
				{ "Smeltery", "Smelters and kilns" },
				{ "InfiniteFuel", "Fires that never go out" },
				{ "Tamer", "Taming and breeding" },
				{ "Prospector", "Mining" },
				{ "OfflineProgress", "Work while you're away" },
				{ "DeathPenalty", "Death penalty" },
				{ "Graveyard", "Tombstones" },
				{ "WellFed", "Food" },
				{ "HaulingSkill", "Carry weight skill" },
				{ "Runeforge", "Weapon imbues" },
				{ "Dye", "Dye your gear" },
				{ "Achievements", "Achievements" },
				{ "EquipmentPanel", "Character gear panel" },
				{ "Storage", "Quick Stack, Ward Organize" },
				{ "Quartermaster", "Craft from chests, Never Pull" },
				{ "LootFilter", "Auto-pickup, Loot Filter" },
				{ "Backpacks", "Backpack" },
				{ "CoinPurse", "Coins" },
				{ "BulkLoad", "Load stations in bulk" },
				{ "Social", "Party and friends" },
				{ "GildedUI", "Look of the UI, F7 window" },
				{ "Camera", "Camera" },
				{ "Graphics", "Haze, fog, shadows, clarity, stars, rain, sun shafts, ocean" },
				{ "CaveFog", "Cave fog" },
				{ "Server", "Server sync, debugging" },
				{ "AdminSettings", "Every server-synced setting (admins only)" },
				{ "Staff", "Players, roles, kick and ban" },
				{ "DevCommands", "Admin commands" },
				{ "AdminAreaCopy", "Copy areas (admin)" }
			};
			advanced = new HashSet<string> { "Server.SyncOtherMods", "Server.VersionCheck", "Graphics.ReflectionResolution", "Graphics.ReflectionSmooth", "Graphics.ReflectionHdr", "Graphics.WaterFoam", "Graphics.Caustics", "Graphics.CausticsStrength" };
			advKey = new Regex("(Debug|Verbose|Logs?$|Logging|Interval|Tick|Budget|Cache|Throttle|Timeout|Migrat|^Load[A-Z]|[A-Za-z][0-9]{3,4}$)", RegexOptions.Compiled);
			internalKeys = new HashSet<(string, string)>();
			adminFrame = -1;
			C("Performance", "CaveFog");
			C("Graphics", "Graphics", "WispColumn", "Camera", "GildedUI");
			C("HUD", "HUD");
			C("Frames", "Frames");
			C("World & Travel", "Teleport", "SwimTweaks", "Exploration", "MeadowsAnywhere", "SkipIntro", "MapStyle", "Sailing", "LongshipHarbor", "Trails", "BossStones", "Wishbone", "AreaReset", "SeedPreview", "Water");
			C("Building & Base", "WardGuard", "BuildInteract", "Resting", "YggdrasilRoot", "AxeCombo", "HomesteadMove", "DvergrBuild", "SlopeAssist", "TerrainTools", "SignStyle", "TraderStalls", "Shipwright", "StationScale", "ShipSalvage");
			C("Farming & Production", "Apiary", "Planting", "Smeltery", "Prospector", "Brewmaster", "OfflineProgress", "InfiniteFuel", "Tamer");
			C("Inventory & Storage", "Storage", "Quartermaster", "Backpacks", "LootFilter", "BulkLoad", "CoinPurse");
			C("Combat & Gear", "EquipmentPanel", "Runeforge", "Dye", "DeathPenalty", "Graveyard", "WellFed", "HaulingSkill");
			C("Social", "Social", "Achievements");
			C("Server & Debug", "Server", "DevCommands", "AdminAreaCopy");
			C("Admin", "Staff", "AdminSettings");
		}

		public static bool IsHudFrame(string m)
		{
			return m?.StartsWith("HUD ") ?? false;
		}

		public static bool IsVanillaFrame(string m)
		{
			return m?.StartsWith("Frames ") ?? false;
		}

		public static bool Collapsible(string page)
		{
			if (!(page == "HUD") && !(page == "Frames"))
			{
				return page == "AdminSettings";
			}
			return true;
		}

		public static Spot Of(IOption o)
		{
			if (o.ServerSynced && !(o is ForeignOption) && !o.Module.StartsWith("ext:"))
			{
				Spot spot = OfBase(o);
				string text = Title(spot.Page);
				return new Spot
				{
					Page = "AdminSettings",
					Section = ((spot.Section != null && spot.Section != text) ? (text + "  ›  " + spot.Section) : text)
				};
			}
			return OfBase(o);
		}

		private static Spot OfBase(IOption o)
		{
			string module = o.Module;
			if (module.StartsWith("ext:"))
			{
				return new Spot
				{
					Page = module
				};
			}
			if (toFrames.TryGetValue(module + "." + o.Key, out var value))
			{
				return new Spot
				{
					Page = "Frames",
					Section = value
				};
			}
			if (IsVanillaFrame(module))
			{
				return new Spot
				{
					Page = "Frames",
					Section = module.Substring(7) + " (game window)"
				};
			}
			if (IsHudFrame(module))
			{
				if (!hudFrameKeys.Contains(o.Key))
				{
					return new Spot
					{
						Page = "HUD",
						Section = module.Substring(4)
					};
				}
				return new Spot
				{
					Page = "Frames",
					Section = module.Substring(4)
				};
			}
			string text = Parent(module);
			string value2;
			string text2 = ((text == module) ? null : (section.TryGetValue(module, out value2) ? value2 : Options.Display(module)));
			if (keySection.TryGetValue(module + "." + o.Key, out var value3))
			{
				text2 = value3;
			}
			bool flag = !Collapsible(text) && o.Key != "Enabled" && (module == "Debug" || advanced.Contains(module + "." + o.Key) || advKey.IsMatch(o.Key));
			return new Spot
			{
				Page = text,
				Section = text2,
				Advanced = flag
			};
		}

		public static string Parent(string m)
		{
			if (m == null || !parent.TryGetValue(m, out var value))
			{
				if (!IsHudFrame(m))
				{
					if (!IsVanillaFrame(m))
					{
						return m;
					}
					return "Frames";
				}
				return "HUD";
			}
			return value;
		}

		public static string PageOf(string module)
		{
			if (module != null)
			{
				if (!module.StartsWith("ext:") && !(module == "HUD") && !(module == "Frames"))
				{
					return Parent(module);
				}
				return module;
			}
			return null;
		}

		public static string Category(string page)
		{
			if (page != null)
			{
				if (!page.StartsWith("ext:"))
				{
					if (!cat.TryGetValue(page, out var value))
					{
						return "Miscellaneous";
					}
					return value;
				}
				return "Other Mods";
			}
			return "Miscellaneous";
		}

		public static string Subtitle(string page)
		{
			if (page == null || !subtitle.TryGetValue(page, out var value))
			{
				return "";
			}
			return value;
		}

		public static string Title(string page)
		{
			return page switch
			{
				"AdminSettings" => "Server Settings", 
				"Frames" => "Frames", 
				"HUD" => "HUD", 
				_ => Options.Display(page), 
			};
		}

		public static bool IsInternal(IOption o)
		{
			if (o.Description == null || !o.Description.StartsWith("Internal:"))
			{
				if (!(o is ForeignOption))
				{
					if (!internalKeys.Contains((o.Module, o.Key)))
					{
						if (o.ServerSynced)
						{
							return !AdminView;
						}
						return false;
					}
					return true;
				}
				return false;
			}
			return true;
		}

		private static bool Internal(IOption o)
		{
			return IsInternal(o);
		}

		public static List<(string cat, List<string> pages)> Group()
		{
			List<string> list = new List<string>();
			if (StaffView)
			{
				list.Add("Staff");
			}
			foreach (IOption item in Visible)
			{
				string page = Of(item).Page;
				if (!list.Contains(page))
				{
					list.Add(page);
				}
			}
			List<(string, List<string>)> list2 = new List<(string, List<string>)>();
			string[] categories = Categories;
			foreach (string c in categories)
			{
				List<string> list3 = list.Where((string p) => Category(p) == c).ToList();
				if (list3.Count > 0)
				{
					list2.Add((c, list3));
				}
			}
			return list2;
		}

		public static List<(string section, List<IOption> opts)> Sections(string page)
		{
			List<(string, List<IOption>)> list = new List<(string, List<IOption>)>();
			List<IOption> list2 = new List<IOption>();
			foreach (IOption item3 in Visible)
			{
				Spot s = Of(item3);
				if (s.Page != page)
				{
					continue;
				}
				if (s.Section == null)
				{
					list2.Add(item3);
					continue;
				}
				int num = list.FindIndex(((string section, List<IOption> opts) x) => x.section == s.Section);
				if (num < 0)
				{
					list.Add((s.Section, new List<IOption> { item3 }));
				}
				else
				{
					list[num].Item2.Add(item3);
				}
			}
			if (page == "HUD")
			{
				int num2 = list.FindIndex(((string section, List<IOption> opts) x) => x.section == "General");
				if (num2 > 0)
				{
					(string, List<IOption>) item = list[num2];
					list.RemoveAt(num2);
					list.Insert(0, item);
				}
			}
			if (page == "Frames")
			{
				int num3 = list.FindIndex(((string section, List<IOption> opts) x) => x.section == "Unlock Frames");
				if (num3 > 0)
				{
					(string, List<IOption>) item2 = list[num3];
					list.RemoveAt(num3);
					list.Insert(0, item2);
				}
			}
			if (list2.Count > 0)
			{
				list.Insert(0, (null, list2));
			}
			return list.Select<(string, List<IOption>), (string, List<IOption>)>(((string section, List<IOption> opts) r) => (section: r.section, StableEnabledFirst(r.opts))).ToList();
		}

		private static List<IOption> StableEnabledFirst(List<IOption> l)
		{
			return l.Where((IOption o) => o.Key == "Enabled").Concat(l.Where((IOption o) => o.Key != "Enabled")).ToList();
		}
	}
	public interface IChoices
	{
		object[] Choices { get; }
	}
	public interface IChoiceLabels
	{
		string ChoiceLabel(object v);
	}
	public sealed class ForeignOption : IOption, IChoices, IChoiceLabels
	{
		public readonly ForeignMod Mod;

		private readonly ConfigEntryBase e;

		internal readonly string HayKey;

		private readonly object[] fixedChoices;

		private static Dictionary<string, string> envBiomes;

		private static List<string> envCache;

		private static EnvMan envCacheOwner;

		public string Module => Mod.Key;

		public string Section => e.Definition.Section;

		public string Key => e.Definition.Key;

		public string Description
		{
			get
			{
				ConfigDescription description = e.Description;
				return ((description != null) ? description.Description : null) ?? "";
			}
		}

		public Type Type => e.SettingType;

		public bool ServerSynced { get; }

		public bool HfSynced { get; }

		public bool AnySync
		{
			get
			{
				if (!ServerSynced)
				{
					if (HfSynced && ConfigSync.SyncOtherMods != null)
					{
						return ConfigSync.SyncOtherMods.Value;
					}
					return false;
				}
				return true;
			}
		}

		public ConfigEntryBase Entry => e;

		public float Min { get; }

		public float Max { get; }

		public bool HasRange { get; }

		public bool EnvName { get; }

		public object[] Choices
		{
			get
			{
				if (!EnvName)
				{
					return fixedChoices;
				}
				List<string> list = EnvNames();
				if (list == null)
				{
					return null;
				}
				List<object> list2 = new List<object> { "" };
				string text = Boxed as string;
				if (!string.IsNullOrEmpty(text) && !list.Contains(text))
				{
					list2.Add(text);
				}
				list2.AddRange(list);
				return list2.ToArray();
			}
		}

		public bool RestartHint { get; }

		public object DefaultBoxed => e.DefaultValue;

		public object Boxed
		{
			get
			{
				try
				{
					return e.BoxedValue;
				}
				catch
				{
					return e.DefaultValue;
				}
			}
			set
			{
				try
				{
					e.BoxedValue = value;
					if (!e.ConfigFile.SaveOnConfigSet)
					{
						ForeignMods.QueueSave(e.ConfigFile);
					}
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("[OtherMods] " + Mod.Name + " › " + Key + ": could not set value: " + ex.Message));
				}
			}
		}

		public string ChoiceLabel(object v)
		{
			string text = v as string;
			if (string.IsNullOrEmpty(text))
			{
				return "(none)";
			}
			if (!EnvName || envBiomes == null || !envBiomes.TryGetValue(text, out var value))
			{
				return text;
			}
			return text + "  <size=12><color=#999180>" + value + "</color></size>";
		}

		private static List<string> EnvNames()
		{
			EnvMan instance = EnvMan.instance;
			if ((Object)(object)instance == (Object)null || instance.m_environments == null)
			{
				return null;
			}
			if (envCache == null || (Object)(object)envCacheOwner != (Object)(object)instance || envCache.Count == 0)
			{
				envCacheOwner = instance;
				envCache = (from x in instance.m_environments
					where x != null && !string.IsNullOrEmpty(x.m_name)
					select x.m_name into x
					where x != "VoxelUnderground"
					select x).Distinct().OrderBy<string, string>((string x) => x, StringComparer.OrdinalIgnoreCase).ToList();
				envBiomes = new Dictionary<string, string>();
				try
				{
					Dictionary<string, List<string>> dictionary = new Dictionary<string, List<string>>();
					foreach (BiomeEnvSetup item2 in instance.m_biomes ?? new List<BiomeEnvSetup>())
					{
						foreach (EnvEntry item3 in item2?.m_environments ?? new List<EnvEntry>())
						{
							if (item3 != null && !string.IsNullOrEmpty(item3.m_environment))
							{
								if (!dictionary.TryGetValue(item3.m_environment, out var value))
								{
									value = (dictionary[item3.m_environment] = new List<string>());
								}
								string item = Widgets.Nice(((object)Unsafe.As<Biome, Biome>(ref item2.m_biome)/*cast due to .constrained prefix*/).ToString());
								if (!value.Contains(item))
								{
									value.Add(item);
								}
							}
						}
					}
					foreach (KeyValuePair<string, List<string>> item4 in dictionary)
					{
						envBiomes[item4.Key] = ((item4.Value.Count > 2) ? (item4.Value[0] + ", " + item4.Value[1] + " +" + (item4.Value.Count - 2)) : string.Join(", ", item4.Value));
					}
				}
				catch
				{
				}
			}
			if (envCache.Count <= 0)
			{
				return null;
			}
			return envCache;
		}

		public void Reset()
		{
			Boxed = e.DefaultValue;
		}

		public bool CanEdit()
		{
			if (!AnySync || (Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer())
			{
				return true;
			}
			return ZNet.instance.LocalPlayerIsAdminOrHost();
		}

		internal ForeignOption(ForeignMod mod, ConfigEntryBase entry, bool synced)
		{
			Mod = mod;
			e = entry;
			ServerSynced = synced;
			HayKey = (mod.Guid ?? mod.Key) + "|" + entry.Definition.Section + "|" + entry.Definition.Key;
			ConfigDescription description = entry.Description;
			AcceptableValueBase val = ((description != null) ? description.AcceptableValues : null);
			if (val != null)
			{
				Type type = ((object)val).GetType();
				if (type.Name.StartsWith("AcceptableValueRange") && (Type == typeof(int) || Type == typeof(float)))
				{
					try
					{
						Min = Convert.ToSingle(type.GetProperty("MinValue").GetValue(val));
						Max = Convert.ToSingle(type.GetProperty("MaxValue").GetValue(val));
						HasRange = Max > Min;
					}
					catch
					{
					}
				}
				else if (type.Name.StartsWith("AcceptableValueList"))
				{
					try
					{
						fixedChoices = ((IEnumerable)type.GetProperty("AcceptableValues").GetValue(val)).Cast<object>().ToArray();
					}
					catch
					{
					}
				}
			}
			string description2 = Description;
			ConfigDescription description3 = entry.Description;
			string text = (description2 + " " + string.Join(" ", ((description3 == null) ? null : description3.Tags?.Select((object x) => x?.ToString() ?? "")) ?? new string[0])).ToLowerInvariant();
			if (Type == typeof(string) && fixedChoices == null)
			{
				string text2 = (Section + " " + Key).ToLowerInvariant();
				EnvName = text.Contains("envman") || (text.Contains("environment") && (text.Contains("name") || text.Contains("preset"))) || text2.Contains("environment") || text2.EndsWith(" env");
			}
			if (!synced)
			{
				HfSynced = ForeignMod.GameplayServerSetting(Section, Key, Type, text);
			}
			RestartHint = text.Contains("restart") || text.Contains("relog") || text.Contains("reload") || text.Contains("requires a new world") || text.Contains("re-log");
		}
	}
	public sealed class ForeignMod
	{
		public string Guid;

		public string Name;

		public string Version;

		public string Key;

		public readonly List<ForeignOption> Options = new List<ForeignOption>();

		public string SyncSource = "none";

		private static readonly string[] LocalSections = new string[16]
		{
			"debug", "diagnostic", "visual", "graphic", "audio", "sound", "ui", "uis", "hud", "control",
			"key", "input", "camera", "about", "client", "local"
		};

		public bool AnySynced => Options.Any((ForeignOption o) => o.ServerSynced);

		internal static bool GameplayServerSetting(string section, string key, Type t, string desc)
		{
			if (t == typeof(KeyCode) || t == typeof(KeyboardShortcut) || t == typeof(Color))
			{
				return false;
			}
			string text = section.ToLowerInvariant();
			if (Regex.Split(text, "[^a-z]+").Any((string w) => LocalSections.Any((string x) => w.StartsWith(x))))
			{
				return false;
			}
			if (desc.Contains("local only") || desc.Contains("client only") || desc.Contains("never synced") || desc.Contains("currently selected"))
			{
				return false;
			}
			if (!desc.Contains("server setting") && !desc.Contains("server-side setting") && !text.Contains("balance") && !(text == "server"))
			{
				return text.StartsWith("server ");
			}
			return true;
		}
	}
	public static class ForeignMods
	{
		private static readonly string[] Libraries = new string[7] { "jotunn", "yamldotnet", "conditionalconfigsync", "serversync", "bepinex", "harmony", "mmhook" };

		private static List<ForeignMod> cache;

		private static float scannedAt = -999f;

		private static readonly HashSet<ConfigFile> watched = new HashSet<ConfigFile>();

		private static readonly HashSet<ConfigFile> pendingSave = new HashSet<ConfigFile>();

		private static float lastQueued;

		public static List<ForeignMod> All
		{
			get
			{
				if (cache == null || Time.unscaledTime - scannedAt > 10f)
				{
					cache = Scan();
					scannedAt = Time.unscaledTime;
				}
				return cache;
			}
		}

		public static event Action Changed;

		public static void QueueSave(ConfigFile f)
		{
			pendingSave.Add(f);
			lastQueued = Time.unscaledTime;
		}

		public static void FlushSaves(float settle = 0f)
		{
			if (pendingSave.Count == 0 || Time.unscaledTime - lastQueued < settle)
			{
				return;
			}
			foreach (ConfigFile item in pendingSave)
			{
				try
				{
					item.Save();
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("[OtherMods] save failed: " + ex.Message));
				}
			}
			pendingSave.Clear();
		}

		public static ForeignMod Find(string key)
		{
			return All.FirstOrDefault((ForeignMod m) => m.Key == key);
		}

		private static List<ForeignMod> Scan()
		{
			List<ForeignMod> list = new List<ForeignMod>();
			Dictionary<string, PluginInfo> pluginInfos;
			try
			{
				pluginInfos = Chainloader.PluginInfos;
			}
			catch
			{
				return list;
			}
			foreach (KeyValuePair<string, PluginInfo> item in pluginInfos.ToList())
			{
				try
				{
					PluginInfo value = item.Value;
					BaseUnityPlugin val = ((value != null) ? value.Instance : null);
					if ((Object)(object)val == (Object)null || value.Metadata == null || value.Metadata.GUID == "spencer.hearthforge")
					{
						continue;
					}
					ConfigFile cfg;
					try
					{
						cfg = val.Config;
					}
					catch
					{
						goto end_IL_0030;
					}
					if (cfg == null)
					{
						continue;
					}
					List<ConfigEntryBase> list2 = (from x in ((IEnumerable<ConfigDefinition>)cfg.Keys).Select((Func<ConfigDefinition, ConfigEntryBase>)delegate(ConfigDefinition k)
						{
							try
							{
								return cfg[k];
							}
							catch
							{
								return (ConfigEntryBase)null;
							}
						})
						where x != null
						select x).ToList();
					if (list2.Count == 0)
					{
						continue;
					}
					string id = (value.Metadata.GUID + " " + value.Metadata.Name).ToLowerInvariant();
					if (Libraries.Any((string l) => id.Contains(l)) && list2.Count((ConfigEntryBase x) => x.SettingType == typeof(bool) || x.SettingType.IsEnum || x.SettingType == typeof(KeyCode) || x.SettingType == typeof(KeyboardShortcut)) < 3)
					{
						continue;
					}
					ForeignMod foreignMod = new ForeignMod
					{
						Guid = value.Metadata.GUID,
						Name = value.Metadata.Name,
						Version = (value.Metadata.Version?.ToString() ?? ""),
						Key = "ext:" + value.Metadata.GUID
					};
					Func<ConfigEntryBase, bool> func = SyncProbe(value, ((object)val).GetType().Assembly);
					foreach (ConfigEntryBase item2 in from x in list2
						orderby x.Definition.Section, x.Definition.Key
						select x)
					{
						bool synced;
						try
						{
							synced = func(item2);
						}
						catch
						{
							synced = true;
						}
						foreignMod.Options.Add(new ForeignOption(foreignMod, item2, synced));
					}
					Options.DisplayNames[foreignMod.Key] = foreignMod.Name;
					if (watched.Add(cfg))
					{
						cfg.SettingChanged += delegate
						{
							ForeignMods.Changed?.Invoke();
						};
					}
					list.Add(foreignMod);
					end_IL_0030:;
				}
				catch (Exception ex)
				{
					Plugin.Log.LogWarning((object)("[OtherMods] skipped " + item.Key + ": " + ex.Message));
				}
			}
			return list.OrderBy<ForeignMod, string>((ForeignMod m) => m.Name, StringComparer.OrdinalIgnoreCase).ToList();
		}

		private static Func<ConfigEntryBase, bool> SyncProbe(PluginInfo info, Assembly asm)
		{
			Type type = null;
			try
			{
				type = asm.GetType("ServerSync.ConfigSync");
			}
			catch
			{
			}
			if (type != null)
			{
				Dictionary<ConfigEntryBase, bool> flags = new Dictionary<ConfigEntryBase, bool>();
				try
				{
					if (type.GetField("configSyncs", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(null) is IEnumerable enumerable)
					{
						foreach (object item in enumerable)
						{
							if (!(item.GetType().GetField("allConfigs", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.GetValue(item) is IEnumerable enumerable2))
							{
								continue;
							}
							foreach (object item2 in enumerable2)
							{
								Type type2 = item2.GetType();
								object? obj2 = type2.GetField("BaseConfig")?.GetValue(item2) ?? type2.GetProperty("BaseConfig")?.GetValue(item2);
								ConfigEntryBase val = (ConfigEntryBase)((obj2 is ConfigEntryBase) ? obj2 : null);
								object obj3 = type2.GetField("SynchronizedConfig")?.GetValue(item2) ?? type2.GetProperty("SynchronizedConfig")?.GetValue(item2);
								if (val != null && obj3 is bool value)
								{
									flags[val] = value;
								}
							}
						}
					}
				}
				catch
				{
				}
				bool value2;
				if (flags.Count > 0)
				{
					return (ConfigEntryBase en) => flags.TryGetValue(en, out value2) && value2;
				}
				return (ConfigEntryBase _) => true;
			}
			bool flag = false;
			try
			{
				flag = info.Dependencies != null && info.Dependencies.Any((BepInDependency d) => d.DependencyGUID.IndexOf("ConditionalConfigSync", StringComparison.OrdinalIgnoreCase) >= 0);
			}
			catch
			{
			}
			if (flag)
			{
				return (ConfigEntryBase _) => true;
			}
			return delegate(ConfigEntryBase en)
			{
				ConfigDescription description = en.Description;
				object[] array = ((description != null) ? description.Tags : null);
				if (array == null)
				{
					return false;
				}
				object[] array2 = array;
				bool flag2 = default(bool);
				foreach (object obj6 in array2)
				{
					if (obj6 != null)
					{
						Type type3 = obj6.GetType();
						FieldInfo fieldInfo = type3.GetField("IsAdminOnly") ?? null;
						PropertyInfo propertyInfo = ((fieldInfo == null) ? type3.GetProperty("IsAdminOnly") : null);
						object obj7 = ((fieldInfo != null) ? fieldInfo.GetValue(obj6) : propertyInfo?.GetValue(obj6));
						int num;
						if (obj7 is bool)
						{
							flag2 = (bool)obj7;
							num = 1;
						}
						else
						{
							num = 0;
						}
						if (((uint)num & (flag2 ? 1u : 0u)) != 0)
						{
							return true;
						}
					}
				}
				return false;
			};
		}
	}
	public class ShortcutRow : OptionRow, IBuildable
	{
		private Button b;

		private TextMeshProUGUI label;

		private static KeyCode[] codes;

		private int startFrame;

		private static readonly KeyCode[] Mods;

		public static ShortcutRow capturing;

		public static bool Busy => (Object)(object)capturing != (Object)null;

		public void Build(RectTransform ctl, Transform _)
		{
			//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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = Theme.Rect("Key", (Transform)(object)ctl);
			Theme.Place(val, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), Vector2.zero, new Vector2(220f, 34f));
			b = Widgets.Button((Transform)(object)val, "", delegate
			{
				if (base.Editable)
				{
					KeybindRow.Capturing = null;
					capturing = this;
					startFrame = Time.frameCount;
				}
			});
			label = ((Component)b).GetComponentInChildren<TextMeshProUGUI>();
			if (codes == null)
			{
				codes = ((KeyCode[])Enum.GetValues(typeof(KeyCode))).Where((KeyCode k) => (int)k != 0 && (int)k < 330 && !Mods.Contains(k)).Distinct().ToArray();
			}
		}

		public unsafe override void Refresh()
		{
			//IL_002e: 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_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			Widgets.SetInteractable((Selectable)(object)b, base.Editable);
			KeyboardShortcut val = ((Option.Boxed is KeyboardShortcut val2) ? val2 : KeyboardShortcut.Empty);
			((TMP_Text)label).text = (((Object)(object)capturing == (Object)(object)this) ? "Press keys…" : ("[ " + (((int)((KeyboardShortcut)(ref val)).MainKey == 0) ? "None" : ((object)(*(KeyboardShortcut*)(&val))/*cast due to .constrained prefix*/).ToString()) + " ]"));
		}

		private void Update()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: 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_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Invalid comparison between Unknown and I4
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Invalid comparison between Unknown and I4
			//IL_0083: 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_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)capturing != (Object)(object)this)
			{
				return;
			}
			((TMP_Text)label).text = "Press keys…  (Esc cancel, Bksp clear)";
			((Graphic)label).color = Color.Lerp(Theme.Gold, Theme.Parchment, Mathf.PingPong(Time.unscaledTime * 2f, 1f));
			if (Time.frameCount < startFrame + 2)
			{
				return;
			}
			KeyCode[] array = codes;
			foreach (KeyCode val in array)
			{
				if (Widgets.KeyDown(val))
				{
					if ((int)val == 8)
					{
						Option.Boxed = KeyboardShortcut.Empty;
					}
					else if ((int)val != 27)
					{
						Option.Boxed = (object)new KeyboardShortcut(val, Mods.Where(Widgets.KeyHeld).ToArray());
					}
					capturing = null;
					((Graphic)label).color = Theme.Gold;
					SettingsPanel.SwallowEscapeFrame = Time.frameCount;
					Refresh();
					break;
				}
			}
		}

		private void OnDisable()
		{
			if ((Object)(object)capturing == (Object)(object)this)
			{
				capturing = null;
			}
		}

		static ShortcutRow()
		{
			KeyCode[] array = new KeyCode[6];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			Mods = (KeyCode[])(object)array;
		}
	}
	public class ColorRow : OptionRow, IBuildable
	{
		private Image sw;

		private TMP_InputField f;

		public void Build(RectTransform ctl, Transform _)
		{
			//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_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = Theme.Rect("Swatch", (Transform)(object)ctl);
			Theme.Place(val, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-150f, 0f), new Vector2(34f, 30f));
			Theme.Img((Component)(object)val, Theme.Slot, Color.white);
			sw = Theme.Img((Component)(object)Theme.Fill("Fill", (Transform)(object)val, 5f), null, Color.white, sliced: false, raycast: false);
			RectTransform val2 = Theme.Rect("Hex", (Transform)(object)ctl);
			Theme.Place(val2, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), Vector2.zero, new Vector2(140f, 34f));
			f = Widgets.Input((Transform)(object)val2, "#RRGGBBAA");
			f.textComponent.alignment = (TextAlignmentOptions)514;
			((UnityEvent<string>)(object)f.onEndEdit).AddListener((UnityAction<string>)delegate(string txt)
			{
				//IL_003f: Unknown result type (might be due to invalid IL or missing references)
				if (!base.Editable)
				{
					Refresh();
				}
				else
				{
					string text = txt.Trim();
					if (!text.StartsWith("#"))
					{
						text = "#" + text;
					}
					Color val3 = default(Color);
					if (ColorUtility.TryParseHtmlString(text, ref val3))
					{
						Option.Boxed = val3;
					}
					Refresh();
				}
			});
		}

		public override void Refresh()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_0024: 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)
			Color val = ((Option.Boxed is Color val2) ? val2 : Color.white);
			((Graphic)sw).color = val;
			((Selectable)f).interactable = base.Editable;
			if (!f.isFocused)
			{
				f.text = "#" + ColorUtility.ToHtmlStringRGBA(val);
			}
		}
	}
	public static class Gilded
	{
		public class StayOnTop : MonoBehaviour
		{
			private void Start()
			{
				((Component)this).transform.SetAsLastSibling();
			}

			private void OnTransformParentChanged()
			{
				((Component)this).transform.SetAsLastSibling();
			}

			private void OnEnable()
			{
				((Component)this).transform.SetAsLastSibling();
			}
		}

		private static readonly Dictionary<(string, float, bool), Sprite> cache = new Dictionary<(string, float, bool), Sprite>();

		private static readonly HashSet<string> missing = new HashSet<string>();

		public const float WindowScale = 0.6f;

		public static bool Pref = true;

		public static readonly Color Gold = Theme.Gold;

		public static readonly Color Amber = Theme.Amber;

		public static readonly Color Text = Theme.Text;

		public static Sprite Frame => Load("g_frame", 52f);

		public static Sprite Slot => Load("g_slot", 24f);

		public static Sprite Banner => Load("g_banner", 44f);

		public static Sprite BarBg => Load("g_bar_bg", 9f);

		public static Sprite BarFill => Load("g_bar_fill", 9f);

		public static Sprite Frame2 => Load("g2_frame", 84f);

		public static Sprite Title2 => Load("g2_title", 170f);

		public static Sprite Plaque2 => Load("g2_plaque", 30f);

		public static Sprite Slot2 => Load("g2_slot", 24f);

		public static Sprite Hover2 => Load("g2_hover", 24f);

		public static Sprite Glow2 => Load("g2_glow", 0f);

		public static Sprite Divider2 => Load("g2_divider", 0f);

		public static Sprite BarBg2 => Load("g2_bar_bg", 11f);

		public static Sprite BarFill2 => Load("g2_bar_fill", 11f);

		public static Sprite Hearth128 => Load("hearth_128", 0f);

		public static Sprite Hearth64 => Load("hearth_64", 0f);

		public static Sprite FrameSmall => Load("g_frame", 52f, 290f);

		public static Sprite SlotSmall => Load("g_slot", 24f, 340f);

		public static Sprite SlotMid => Load("g_slot", 24f, 200f);

		public static Sprite Window => G3("g3_window", 152f);

		public static Sprite WindowCorners => G3("g3_window_corners", 152f);

		public static Sprite Frame3 => G3("g3_frame", 36f);

		public static Sprite Inset => G3("g3_inset", 30f);

		public static Sprite InsetSmall => G3("g3_inset", 30f, 400f);

		public static Sprite Row => G3("g3_row", 24f);

		public static Sprite Button => G3("g3_button", 16f);

		public static Sprite ButtonPress => G3("g3_button_press", 16f);

		public static Sprite ButtonGlow => G3("g3_button_glow", 16f);

		public static Sprite Tab => G3("g3_tab", 20f);

		public static Sprite TabSel => G3("g3_tab_sel", 20f);

		public static Sprite Toggle => G3("g3_toggle", 27f);

		public static Sprite ToggleFill => G3("g3_toggle_fill", 27f);

		public static Sprite Knob => G3("g3_knob", 0f);

		public static Sprite KnobSmall => G3("g3_knob_small", 0f);

		public static Sprite SliderTrack => G3("g3_slider_track", 17f);

		public static Sprite SliderFill => G3("g3_slider_fill", 11f);

		public static Sprite Input => G3("g3_input", 12f);

		public static Sprite Header => G3("g3_header", 60f);

		public static Sprite TitleBar => G3("g3_titlebar", 16f);

		public static Sprite Crest => G3("g3_crest", 0f);

		public static Sprite Title3 => G3("g3_title", 200f);

		public static Sprite Slot3 => G3("g3_slot", 22f);

		public static Sprite Ring3 => G3("g3_ring", 0f);

		public static Sprite SlotHover3 => G3("g3_slot_hover", 22f);

		public static Sprite Glow3 => G3("g3_glow", 0f);

		public static Sprite Divider3 => G3("g3_divider", 0f);

		public static Sprite BarBg3 => G3("g3_bar_bg", 12f);

		public static Sprite BarFill3 => G3("g3_bar_fill", 6f);

		public static Sprite BarGold3 => G3("g3_bar_gold", 6f);

		public static Sprite Scroll => G3("g3_scroll", 8f);

		public static Sprite Chevron => G3("g3_chevron", 0f);

		public static Sprite Load(string name, float border, float ppu = 100f)
		{
			return Load(name, border, ppu, mips: false);
		}

		public static Sprite Load(string name, float border, float ppu, bool mips)
		{
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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_00ec: Expected O, but got Unknown
			//IL_0184: 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_01a3: Unknown result type (might be due to invalid IL or missing references)
			(string, float, bool) key = (name, ppu, mips);
			if (cache.TryGetValue(key, out var value) && (Object)(object)value != (Object)null)
			{
				return value;
			}
			if (missing.Contains(name))
			{
				return null;
			}
			try
			{
				using Stream stream = typeof(Gilded).Assembly.GetManifestResourceStream("Hearthforge.assets." + name + ".png");
				if (stream == null)
				{
					missing.Add(name);
					Plugin.Log.LogWarning((object)("[Gilded] missing embedded art " + name));
					return null;
				}
				byte[] array = new byte[stream.Length];
				int num;
				for (int i = 0; i < array.Length; i += num)
				{
					num = stream.Read(array, i, array.Length - i);
					if (num <= 0)
					{
						break;
					}
				}
				Texture2D val = new Texture2D(2, 2, (TextureFormat)4, mips)
				{
					name = "HF_" + name,
					filterMode = (FilterMode)1,
					wrapMode = (TextureWrapMode)1,
					anisoLevel = 0
				};
				if (!ImageConversion.LoadImage(val, array, mips))
				{
					missing.Add(name);
					return null;
				}
				((Texture)val).filterMode = (FilterMode)((!mips) ? 1 : 2);
				((Texture)val).wrapMode = (TextureWrapMode)1;
				if (mips)
				{
					((Texture)val).mipMapBias = -0.35f;
				}
				float num2 = Mathf.Min(border, (float)((Texture)val).width / 2f - 1f);
				float num3 = Mathf.Min(border, (float)((Texture)val).height / 2f - 1f);
				value = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), ppu, 0u, (SpriteMeshType)0, new Vector4(num2, num3, num2, num3));
				((Object)value).name = "HF_" + name;
				cache[key] = value;
				return value;
			}
			catch (Exception ex)
			{
				missing.Add(name);
				Plugin.Log.LogWarning((object)("[Gilded] could not load " + name + ": " + ex.Message));
				return null;
			}
		}

		private static Sprite G3(string n, float border, float ppu = 200f)
		{
			if (!Pref)
			{
				return null;
			}
			return Load(n, border, ppu, mips: true);
		}

		public static void Fit(Image img, Sprite s, float screenBorder = 0f)
		{
			//IL_001b: 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)
			if (!((Object)(object)img == (Object)null) && !((Object)(object)s == (Object)null))
			{
				img.sprite = s;
				float num = Mathf.Max(s.border.x, s.border.y);
				if (num <= 0f)
				{
					img.type = (Type)0;
					return;
				}
				img.type = (Type)1;
				img.fillCenter = true;
				img.pixelsPerUnitMultiplier = ((screenBorder > 0f) ? (num * 100f / s.pixelsPerUnit / screenBorder) : 1f);
			}
		}

		public static Image WindowBg(RectTransform w)
		{
			//IL_004e: 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_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: 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_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			Image val = ((Component)w).GetComponent<Image>() ?? ((Component)w).gameObject.AddComponent<Image>();
			if ((Object)(object)Window == (Object)null)
			{
				val.sprite = Theme.Frame;
				val.type = (Type)1;
				((Graphic)val).color = Color.white;
				Theme.Shadow((Component)(object)val, 8f);
				return val;
			}
			((Graphic)val).color = Color.white;
			((Graphic)val).raycastTarget = true;
			val.sprite = Window;
			val.type = (Type)1;
			val.fillCenter = true;
			val.pixelsPerUnitMultiplier = 1.6666666f;
			RectTransform component = new GameObject("GildedCorners", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
			((Transform)component).SetParent((Transform)(object)w, false);
			component.anchorMin = Vector2.zero;
			component.anchorMax = Vector2.one;
			Vector2 offsetMin = (component.offsetMax = Vector2.zero);
			component.offsetMin = offsetMin;
			Image obj = ((Component)component).gameObject.AddComponent<Image>();
			obj.sprite = WindowCorners;
			obj.type = (Type)1;
			obj.fillCenter = false;
			obj.pixelsPerUnitMultiplier = 1.6666666f;
			((Graphic)obj).raycastTarget = false;
			((Component)component).gameObject.AddComponent<StayOnTop>();
			return val;
		}

		public static void Apply(Image img, Sprite s, float screenBorder, float texBorder)
		{
			if (!((Object)(object)img == (Object)null) && !((Object)(object)s == (Object)null))
			{
				img.sprite = s;
				img.type = (Type)1;
				img.fillCenter = true;
				img.pixelsPerUnitMultiplier = ((texBorder > 0f && screenBorder > 0f) ? (texBorder / screenBorder) : 1f);
			}
		}
	}
	public static class HfCanvas
	{
		private sealed class Entry
		{
			public CanvasScaler S;

			public float Match;
		}

		public static ModOption<bool> Follow;

		private static readonly List<Entry> list = new List<Entry>();

		private static float nextCheck;

		private static float lastFactor = -1f;

		private static int lastW;

		private static int lastH;

		private static bool lastOn;

		private static float guiCached = 1f;

		private static float guiAt = -1f;

		private static bool On
		{
			get
			{
				if (Follow != null)
				{
					return Follow.Value;
				}
				return true;
			}
		}

		public static float GuiScaleIfFollowing
		{
			get
			{
				if (!On)
				{
					return 1f;
				}
				return GameGuiScale();
			}
		}

		internal static event Action Changed;

		internal static void Bind()
		{
			Follow = Options.Bind("UI", "FollowGameGuiScale", def: true, "Hearthforge windows and HUD follow the game's GUI scale (Settings › Accessibility › GUI scale), so they match vanilla's size on every screen shape. At 16:9 and 100 % nothing changes. Off = the old fixed 1920x1080 scaling", synced: false);
			Follow.Changed += delegate
			{
				lastFactor = -1f;
				ApplyAll();
			};
		}

		public static void Register(CanvasScaler sc)
		{
			if ((Object)(object)sc == (Object)null)
			{
				return;
			}
			for (int i = 0; i < list.Count; i++)
			{
				if ((Object)(object)list[i].S == (Object)(object)sc)
				{
					return;
				}
			}
			Entry entry = new Entry
			{
				S = sc,
				Match = sc.matchWidthOrHeight
			};
			list.Add(entry);
			Apply(entry, Factor());
		}

		private static float GameGuiScale()
		{
			if (Time.unscaledTime < guiAt)
			{
				return guiCached;
			}
			guiAt = Time.unscaledTime + 0.5f;
			try
			{
				guiCached = Mathf.Clamp(PlatformPrefs.GetFloat("GuiScale", 1f), 0.5f, 3f);
			}
			catch
			{
				guiCached = 1f;
			}
			return guiCached;
		}

		private static float Factor()
		{
			return Mathf.Max(0.1f, Mathf.Min((float)Screen.width / 1920f, (float)Screen.height / 1080f) * GameGuiScale());
		}

		private static void Apply(Entry e, float f)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Invalid comparison between Unknown and I4
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			CanvasScaler s = e.S;
			if ((Object)(object)s == (Object)null)
			{
				return;
			}
			if (On)
			{
				if ((int)s.uiScaleMode != 0)
				{
					s.uiScaleMode = (ScaleMode)0;
				}
				if (Mathf.Abs(s.scaleFactor - f) > 0.0001f)
				{
					s.scaleFactor = f;
				}
			}
			else if ((int)s.uiScaleMode != 1)
			{
				s.uiScaleMode = (ScaleMode)1;
				s.referenceResolution = new Vector2(1920f, 1080f);
				s.matchWidthOrHeight = e.Match;
			}
		}

		private static void ApplyAll()
		{
			float f = Factor();
			for (int num = list.Count - 1; num >= 0; num--)
			{
				if ((Object)(object)list[num].S == (Object)null)
				{
					list.RemoveAt(num);
				}
				else
				{
					Apply(list[num], f);
				}
			}
			lastFactor = f;
			lastW = Screen.width;
			lastH = Screen.height;
			lastOn = On;
			try
			{
				HfCanvas.Changed?.Invoke();
			}
			catch
			{
			}
		}

		internal static void Tick()
		{
			if (list.Count != 0 && !(Time.unscaledTime < nextCheck))
			{
				nextCheck = Time.unscaledTime + 1f;
				if (Screen.width != lastW || Screen.height != lastH || On != lastOn || Mathf.Abs(Factor() - lastFactor) > 0.0001f)
				{
					ApplyAll();
				}
			}
		}
	}
	[HarmonyPatch]
	internal static class InputBlock
	{
		private static readonly FieldRef<GameObject> tooltipObj = AccessTools.StaticFieldRefAccess<GameObject>(AccessTools.Field(typeof(UITooltip), "m_tooltip"));

		private static bool Blocking
		{
			get
			{
				if (!SettingsPanel.IsOpen && !HudModule.EditMode && !ItemPicker.AnyOpen && !ZoneResetModule.DialogOpen && !BackpackModule.PromptOpen && !DyeModule.PanelOpen && !FermenterModule.PanelOpen && !HomesteadModule.BpWindow.IsOpen && !SignStyleModule.Editor.IsOpen && !HomesteadModule.UnpackWindow.IsOpen && !HomesteadModule.PackSummary.IsOpen && !KilnGuard.Confirm.IsOpen && !StringEditor.IsOpen && !ConfirmDialog.IsOpen && !ShipStyleModule.Picker.IsOpen)
				{
					return SocialModule.SocialWindow.IsOpen;
				}
				return true;
			}
		}

		internal static bool Any => Blocking;

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Menu), "IsVisible")]
		private static void Visible(ref bool __result)
		{
			if (Blocking)
			{
				__result = true;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Menu), "IsActive")]
		private static void Active(ref bool __result)
		{
			if (Blocking)
			{
				__result = true;
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(UITooltip), "OnHoverStart")]
		private static void Reparent(UITooltip __instance)
		{
			GameObject val = tooltipObj.Invoke();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Canvas componentInParent = ((Component)__instance).GetComponentInParent<Canvas>();
			if (!((Object)(object)componentInParent == (Object)null))
			{
				Transform transform = ((Component)componentInParent.rootCanvas).transform;
				if ((Object)(object)val.transform.parent != (Object)(object)transform)
				{
					val.transform.SetParent(transform, false);
				}
				val.transform.SetAsLastSibling();
				CanvasGroup obj = val.GetComponent<CanvasGroup>() ?? val.AddComponent<CanvasGroup>();
				obj.blocksRaycasts = false;
				obj.interactable = false;
			}
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")]
		private static bool Cursor()
		{
			if (!Blocking)
			{
				return true;
			}
			if ((Object)(object)EventSystem.current == (Object)null)
			{
				UiFocus.Grab();
			}
			ZCursor.LockState = (CursorLockMode)0;
			ZCursor.Show();
			return false;
		}

		[HarmonyPrefix]
		[HarmonyPatch(typeof(Menu), "Update")]
		private static bool NoPauseMenu()
		{
			if (!Blocking)
			{
				return SettingsPanel.SwallowEscapeFrame != Time.frameCount;
			}
			return false;
		}
	}
	public class ItemPicker : MonoBehaviour
	{
		private static readonly HashSet<ItemPicker> open = new HashSet<ItemPicker>();

		public string Title = "Items";

		public Func<ItemDrop, bool> Filter = (ItemDrop _) => true;

		public Func<ItemDrop, bool> IsSelected = (ItemDrop _) => false;

		public Action<ItemDrop> OnClick;

		public string SelectedHeader = "Selected";

		public Action OnClosed;

		public List<(string label, Action act)> ExtraButtons = new List<(string, Action)>();

		private GameObject canvasGo;

		private RectTransform resultContent;

		private RectTransform selectedContent;

		private TMP_InputField search;

		private TextMeshProUGUI countText;

		private TextMeshProUGUI titleLabel;

		private TextMeshProUGUI selHeader;

		private List<ItemDrop> all;

		private const int MaxResults = 240;

		public static bool AnyOpen => open.Count > 0;

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

		public static ItemPicker Create(string name)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			GameObject val = new GameObject("HF_ItemPicker_" + name);
			Object.DontDestroyOnLoad((Object)val);
			return val.AddComponent<ItemPicker>();
		}

		public void Toggle()
		{
			if (IsOpen)
			{
				Close();
			}
			else
			{
				Open();
			}
		}

		public void Open()
		{
			if (!((Object)(object)ObjectDB.instance == (Object)null))
			{
				if ((Object)(object)canvasGo == (Object)null)
				{
					Build();
				}
				all = (from g in ObjectDB.instance.m_items
					where (Object)(object)g != (Object)null
					select g.GetComponent<ItemDrop>() into d
					where (Object)(object)d != (Object)null && d.m_itemData?.m_shared != null && d.m_itemData.m_shared.m_icons != null && d.m_itemData.m_shared.m_icons.Length != 0
					orderby Util.Loc(d.m_itemData.m_shared.m_name)
					select d).ToList();
				canvasGo.SetActive(true);
				open.Add(this);
				((TMP_Text)titleLabel).text = Title;
				((TMP_Text)selHeader).text = SelectedHeader;
				search.text = "";
				Refresh();
			}
		}

		public void Close()
		{
			if ((Object)(object)canvasGo != (Object)null)
			{
				canvasGo.SetActive(false);
			}
			open.Remove(this);
			UITooltip.HideTooltip();
			OnClosed?.Invoke();
		}

		private void Update()
		{
			if (IsOpen && ZInput.GetKeyDown((KeyCode)27, false))
			{
				Close();
				SettingsPanel.SwallowEscapeFrame = Time.frameCount;
			}
			if (IsOpen)
			{
				Cursor.lockState = (CursorLockMode)0;
				Cursor.visible = true;
			}
		}

		private void Build()
		{
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Expected O, but got Unknown
			//IL_009a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: 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_01a0: 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_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_022b: Unknown result type (might be due to invalid IL or missing references)
			//IL_023a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_036d: Unknown result type (might be due to invalid IL or missing references)
			//IL_037c: Unknown result type (might be due to invalid IL or missing references)
			//IL_038b: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_03d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Unknown result type (might be due to invalid IL or missing references)
			//IL_0418: Unknown result type (might be due to invalid IL or missing references)
			//IL_0435: Unknown result type (might be due to invalid IL or missing references)
			//IL_0444: Unknown result type (might be due to invalid IL or missing references)
			//IL_0453: Unknown result type (might be due to invalid IL or missing references)
			//IL_0462: Unknown result type (might be due to invalid IL or missing references)
			//IL_047c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_04dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0514: Unknown result type (might be due to invalid IL or missing references)
			canvasGo = new GameObject("Canvas", new Type[4]
			{
				typeof(RectTransform),
				typeof(Canvas),
				typeof(CanvasScaler),
				typeof(GraphicRaycaster)
			});
			canvasGo.transform.SetParent(((Component)this).transform, false);
			Canvas component = canvasGo.GetComponent<Canvas>();
			component.renderMode = (RenderMode)0;
			component.sortingOrder = 30010;
			CanvasScaler component2 = canvasGo.GetComponent<CanvasScaler>();
			component2.uiScaleMode = (ScaleMode)1;
			component2.referenceResolution = new Vector2(1920f, 1080f);
			component2.matchWidthOrHeight = 0.5f;
			HfCanvas.Register(component2);
			RectTransform val = Theme.Rect("Window", canvasGo.transform);
			Theme.Place(val, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(1000f, 680f));
			Gilded.WindowBg(val);
			RectTransform val2 = Theme.Rect("Title", (Transform)(object)val, new Vector2(0f, 1f), new Vector2(1f, 1f), new Vector2(10f, -60f), new Vector2(-10f, -10f));
			Theme.TitleBarImg((Component)(object)val2);
			((Component)val2).gameObject.AddComponent<Draggable>().Target = val;
			titleLabel = Theme.Label((Transform)(object)val2, Title, 28f, Theme.Gold, (TextAlignmentOptions)513, header: true);
			((TMP_Text)titleLabel).rectTransform.offsetMin = new Vector2(16f, 0f);
			RectTransform obj = Theme.Rect("Close", (Transform)(object)val2);
			Theme.Place(obj, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-8f, 0f), new Vector2(40f, 36f));
			Widgets.Button((Transform)(object)obj, "x", Close, 20f);
			RectTransform val3 = Theme.Rect("Search", (Transform)(object)val2);
			Theme.Place(val3, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-56f, 0f), new Vector2(300f, 34f));
			search = Widgets.Input((Transform)(object)val3, "Search all items…");
			((UnityEvent<string>)(object)search.onValueChanged).AddListener((UnityAction<string>)delegate
			{
				Refresh();
			});
			float num = -364f;
			foreach (var extraButton in ExtraButtons)
			{
				string item = extraButton.label;
				Action item2 = extraButton.act;
				RectTransform obj2 = Theme.Rect("Btn", (Transform)(object)val2);
				Theme.Place(obj2, new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(num, 0f), new Vector2(110f, 34f));
				Action a = item2;
				Widgets.Button((Transform)(object)obj2, item, delegate
				{
					a();
					Refresh();
				}, 14f);
				num -= 116f;
			}
			RectTransform val4 = Theme.Rect("Results", (Transform)(object)val, new Vector2(0f, 0f), new Vector2(0.64f, 1f), new Vector2(14f, 40f), new Vector2(-6f, -70f));
			Theme.Img((Component)(object)val4, Theme.Slot, Color.white);
			resultContent = Scroll(val4, grid: true);
			RectTransform val5 = Theme.Rect("Selected", (Transform)(object)val, new Vector2(0.64f, 0f), new Vector2(1f, 1f), new Vector2(6f, 40f), new Vector2(-14f, -100f));
			Theme.Img((Component)(object)val5, Theme.Slot, Color.white);
			RectTransform parent = Theme.Rect("Header", (Transform)(object)val, new Vector2(0.64f, 1f), new Vector2(1f, 1f), new Vector2(6f, -98f), new Vector2(-14f, -70f));
			selHeader = Theme.Label((Transform)(object)parent, SelectedHeader, 18f, Theme.Gold, (TextAlignmentOptions)513, header: true);
			((TMP_Text)selHeader).rectTransform.offsetMin = new Vector2(8f, 0f);
			selectedContent = Scroll(val5, grid: false);
			RectTransform parent2 = Theme.Rect("Foot", (Transform)(object)val, new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(18f, 8f), new Vector2(-18f, 36f));
			countText = Theme.Label((Transform)(object)parent2, "", 13f, Theme.TextDim, (TextAlignmentOptions)513);
			canvasGo.SetActive(false);
		}

		private static RectTransform Scroll(RectTransform parent, bool grid)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0081: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			ScrollRect obj = ((Component)parent).gameObject.AddComponent<ScrollRect>();
			obj.horizontal = false;
			obj.scrollSensitivity = 30f;
			SmoothScroll.Attach(obj);
			RectTransform val = Theme.Fill("Viewport", (Transform)(object)parent, 6f);
			((Component)val).gameObject.AddComponent<RectMask2D>();
			RectTransform val2 = Theme.Rect("Content", (Transform)(object)val);
			val2.anchorMin = new Vector2(0f, 1f);
			val2.anchorMax = new Vector2(1f, 1f);
			val2.pivot = new Vector2(0.5f, 1f);
			Vector2 offsetMin = (val2.offsetMax = Vector2.zero);
			val2.offsetMin = offsetMin;
			if (grid)
			{
				GridLayoutGroup obj2 = ((Component)val2).gameObject.AddComponent<GridLayoutGroup>();
				obj2.cellSize = new Vector2(196f, 52f);
				obj2.spacing = new Vector2(6f, 6f);
			}
			else
			{
				VerticalLayoutGroup obj3 = ((Component)val2).gameObject.AddComponent<VerticalLayoutGroup>();
				((HorizontalOrVerticalLayoutGroup)obj3).spacing = 4f;
				((HorizontalOrVerticalLayoutGroup)obj3).childControlHeight = false;
				((HorizontalOrVerticalLayoutGroup)obj3).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)obj3).childForceExpandHeight = false;
			}
			((Component)val2).gameObject.AddComponent<ContentSizeFitter>().verticalFit = (FitMode)2;
			obj.viewport = val;
			obj.content = val2;
			return val2;
		}

		public void Refresh()
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			if (!IsOpen)
			{
				return;
			}
			foreach (Transform item in (Transform)resultContent)
			{
				Object.Destroy((Object)(object)((Component)item).gameObject);
			}
			foreach (Transform item2 in (Transform)selectedContent)
			{
				Object.Destroy((Object)(object)((Component)item2).gameObject);
			}
			string q = search.text.Trim();
			List<ItemDrop> list = all.Where((ItemDrop d) => Filter(d) && (q.Length == 0 || Util.Loc(d.m_itemData.m_shared.m_name).IndexOf(q, StringComparison.OrdinalIgnoreCase) >= 0 || ((Object)d).name.IndexOf(q, StringComparison.OrdinalIgnoreCase) >= 0)).ToList();
			foreach (ItemDrop item3 in list.Take(240))
			{
				Entry((Transform)(object)resultContent, item3, 196f);
			}
			List<ItemDrop> list2 = all.Where(IsSelected).ToList();
			foreach (ItemDrop item4 in list2)
			{
				Entry((Transform)(object)selectedContent, item4, 0f);
			}
			((TMP_Text)countText).text = string.Format("{0} items match{1} · {2} selected · click an item to toggle", list.Count, (list.Count > 240) ? $" (showing {240}, refine your search)" : "", list2.Count);
		}

		private void Entry(Transform parent, ItemDrop d, float w)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: 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_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Expected O, but got Unknown
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: 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_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = Theme.Rect("Item", parent);
			val.sizeDelta = new Vector2(w, 52f);
			bool flag = IsSelected(d);
			Image targetGraphic = Theme.Img((Component)(object)val, Theme.Slot, (Color)(flag ? new Color(1f, 0.85f, 0.45f) : Color.white));
			Button obj = ((Component)val).gameObject.AddComponent<Button>();
			((Selectable)obj).targetGraphic = (Graphic)(object)targetGraphic;
			ColorBlock colors = ((Selectable)obj).colors;
			((ColorBlock)(ref colors)).highlightedColor = new Color(1.3f, 1.2f, 1f);
			((Selectable)obj).colors = colors;
			((UnityEvent)obj.onClick).AddListener((UnityAction)delegate
			{
				OnClick?.Invoke(d);
				Refresh();
			});
			RectTransform obj2 = Theme.Rect("Icon", (Transform)(object)val);
			Theme.Place(obj2, new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(6f, 0f), new Vector2(42f, 42f));
			Theme.Img((Component)(object)obj2, d.m_itemData.GetIcon(), Color.white, sliced: false, raycast: false).preserveAspect = true;
			TextMeshProUGUI obj3 = Theme.Label((Transform)(object)val, Util.Loc(d.m_itemData.m_shared.m_name), 15f, flag ? Theme.Gold : Theme.Text, (TextAlignmentOptions)513);
			((TMP_Text)obj3).rectTransform.offsetMin = new Vector2(54f, 0f);
			((TMP_Text)obj3).rectTransform.offsetMax = new Vector2(-4f, 0f);
			GameObject val2 = Widgets.TooltipPrefab();
			if ((Object)(object)val2 != (Object)null)
			{
				UITooltip obj4 = ((Component)val).gameObject.AddComponent<UITooltip>();
				obj4.m_tooltipPrefab = val2;
				obj4.m_topic = d.m_itemData.m_shared.m_name;
				obj4.m_text = ((Object)d).name;
			}
		}
	}
	public static class RuneFont
	{
		private static TMP_FontAsset font;

		private static bool tried;

		public static TMP_FontAsset Font
		{
			get
			{
				Ensure();
				return font;
			}
		}

		public static void Ensure()
		{
			if (tried)
			{
				return;
			}
			tried = true;
			try
			{
				string text = Path.Combine(Paths.CachePath, "Hearthforge-NotoSansRunic-Regular.ttf");
				using (Stream stream = typeof(RuneFont).Assembly.GetManifestResourceStream("Hearthforge.assets.NotoSansRunic-Regular.ttf"))
				{
					if (stream == null)
					{
						Plugin.Log.LogWarning((object)"[Runes] rune font missing from the DLL");
						return;
					}
					byte[] array = new byte[stream.Length];
					int num;
					for (int i = 0; i < array.Length; i += num)
					{
						num = stream.Read(array, i, array.Length - i);
						if (num <= 0)
						{
							break;
						}
					}
					if (!File.Exists(text) || new FileInfo(text).Length != array.Length)
					{
						Directory.CreateDirectory(Path.GetDirectoryName(text));
						File.WriteAllBytes(text, array);
					}
				}
				font = TMP_FontAsset.CreateFontAsset(text, 0, 64, 6, (GlyphRenderMode)4165, 512, 512);
				if ((Object)(object)font == (Object)null)
				{
					Plugin.Log.LogWarning((object)"[Runes] could not create the rune font");
					return;
				}
				((Object)font).name = "HF_NotoSansRunic";
				StringBuilder stringBuilder = new StringBuilder();
				for (int j = 5792; j <= 5880; j++)
				{
					stringBuilder.Append((char)j);
				}
				string text2 = default(string);
				font.TryAddCharacters(stringBuilder.ToString(), ref text2, false);
				List<TMP_FontAsset> fallbackFontAssets = TMP_Settings.fallbackFontAssets;
				if (fallbackFontAssets != null && !fallbackFontAssets.Contains(font))
				{
					fallbackFontAssets.Add(font);
				}
				TMP_FontAsset[] array2 = (TMP_FontAsset[])(object)new TMP_FontAsset[2]
				{
					Theme.Body,
					Theme.Norse
				};
				foreach (TMP_FontAsset val in array2)
				{
					if ((Object)(object)val != (Object)null)
					{
						if (val.fallbackFontAssetTable == null)
						{
							val.fallbackFontAssetTable = new List<TMP_FontAsset>();
						}
						if (!val.fallbackFontAssetTable.Contains(font))
						{
							val.fallbackFontAssetTable.Add(font);
						}
					}
				}
				Plugin.Log.LogInfo((object)("[Runes] rune font ready (fallback for U+16A0-U+16F8)" + (string.IsNullOrEmpty(text2) ? "" : (", missing " + text2.Length))));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("[Runes] rune font: " + ex.Message));
			}
		}
	}
	public class SettingsPanel : MonoBehaviour
	{
		private sealed class CloseHover : MonoBehaviour, IPointerEnterHandler, IEventSystemHandler, IPointerExitHandler
		{
			public Image Img;

			public Sprite Normal;

			public Sprite Hover;

			public void OnPointerEnter(PointerEventData e)
			{
				if ((Object)(object)Img != (Object)null && (Object)(object)Img.sprite != (Object)(object)Hover)
				{
					Img.sprite = Hover;
				}
			}

			public void OnPointerExit(PointerEventData e)
			{
				if ((Object)(object)Img != (Object)null && (Object)(object)Img.sprite != (Object)(object)Normal)
				{
					Img.sprite = Normal;
				}
			}

			private void OnDisable()
			{
				if ((Object)(object)Img != (Object)null)
				{
					Img.sprite = Normal;
				}
			}
		}

		public static ModOption<KeyCode> ToggleKey;

		public static ModOption<float> UiScale;

		public static ModOption<float> PanelX;

		public static ModOption<float> PanelY;

		public static int SwallowEscapeFrame = -1;

		private GameObject canvasGo;

		private RectTransform window;

		private RectTransform tabsContent;

		private RectTransform listContent;

		private RectTransform popupLayer;

		private CanvasGroup group;

		private TMP_InputField search;

		private TextMeshProUGUI statusText;

		private TextMeshProUGUI headerText;

		private readonly List<OptionRow> rows = new List<OptionRow>();

		private readonly Dictionary<string, (Image bg, TextMeshProUGUI txt, Image dot)> tabs = new Dictionary<string, (Image, TextMeshProUGUI, Image)>();

		private static ModOption<string> Collapsed;

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

		private string activeModule;

		private bool open;

		private bool dirty;

		private bool tabsDirty;

		private bool staffDirty;

		private bool lastAdminView = true;

		private bool lastStaffView;

		private float anim;

		private readonly Queue<Action> pendingRows = new Queue<Action>();

		private static readonly Dictionary<string, string> hayCache = new Dictionary<string, string>();

		private static readonly HashSet<string> haySeen = new HashSet<string>();

		private static readonly List<string> hayDrop = new List<string>();

		private static int hayOthers = -1;

		private static bool hayHooked;

		private static readonly Dictionary<IOption, string> hayOwn = new Dictionary<IOption, string>();

		private static bool textRefit;

		private static readonly List<RowFit> fitBuf = new List<RowFit>();

		private float fitK = 1f;

		private float lastK = -1f;

		private float pendingSearchAt = -1f;

		private bool tweening;

		private bool typeDirty;

		private static bool fitDirty;

		private float loggedK = -1f;

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

		private readonly Dictionary<string, RectTransform> secRects = new Dictionary<string, RectTransform>();

		private readonly List<RectTransform> secBodies = new List<RectTransform>();

		private string staffId = "";

		public static SettingsPanel Instance { get; private set; }

		public static bool IsOpen
		{
			get
			{
				if ((Object)(object)Instance != (Object)null)
				{
					return Instance.open;
				}
				return false;
			}
		}

		public static void BindOptions()
		{
			HfCanvas.Bind();
			Options.KeyNames["Graphics.ReflectionHdr"] = "HDR Reflections";
			Options.KeyNames["Graphics.ReflectionSmooth"] = "Smooth Reflection Updates";
			if (!hayHooked)
			{
				hayHooked = true;
				Options.ListChanged += delegate
				{
					hayCache.Clear();
					hayOwn.Clear();
				};
			}
			ToggleKey = Options.Bind<KeyCode>("UI", "ToggleKey", (KeyCode)288, "Open/close the Hearthforge settings panel", synced: false);
			UiScale = Options.Bind("UI", "PanelScale", 1f, "Settings panel scale", synced: false, 0.6f, 1.6f);
			PanelX = Options.Bind("UI", "PanelX", 0f, "Panel X offset (drag the title bar)", synced: false, -1500f, 1500f);
			SmoothScroll.Speed = Options.Bind("UI", "ScrollSpeed", 50f, "Mouse-wheel scroll distance per notch in settings and lists (px)", synced: false, 10f, 200f);
			PanelY = Options.Bind("UI", "PanelY", 0f, "Panel Y offset (drag the title bar)", synced: false, -900f, 900f);
			UiScale.Changed += delegate
			{
				fitDirty = true;
			};
			PanelX.Changed += delegate
			{
				fitDirty = true;
			};
			PanelY.Changed += delegate
			{
				fitDirty = true;
			};
			HfCanvas.Changed += delegate
			{
				fitDirty = true;
			};
			Collapsed = Options.Bind("UI", "CollapsedGroups", string.Join("|", F7Catalog.Categories) + "|Other Mods", "Internal: F7 categories folded shut (|-separated)", synced: false);
		}

		private void Awake()
		{
			Instance = this;
			((BaseUnityPlugin)Plugin.Instance).Config.SettingChanged += delegate
			{
				dirty = true;
			};
			Options.ListChanged += delegate
			{
				tabsDirty = true;
			};
			ForeignMods.Changed += delegate
			{
				dirty = true;
			};
			Staff.Changed += delegate
			{
				staffDirty = true;
				tabsDirty = true;
			};
		}

		private void Update()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: 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_0150: 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)
			if ((Object)(object)KeybindRow.Capturing == (Object)null && !ShortcutRow.Busy && (int)ToggleKey.Value != 0 && Widgets.KeyDown(ToggleKey.Value) && !InTextField())
			{
				Toggle();
			}
			else if (open && (Object)(object)KeybindRow.Capturing == (Object)null && (Object)(object)ClickActivate.Editing == (Object)null && !StringEditor.IsOpen && !ShortcutRow.Busy && Widgets.KeyDown((KeyCode)27) && SwallowEscapeFrame != Time.frameCount)
			{
				Toggle();
				SwallowEscapeFrame = Time.frameCount;
			}
			if ((Object)(object)group != (Object)null)
			{
				float num = (open ? 1 : 0);
				float num2 = UiScale.Value * fitK;
				if (anim != num || num2 != lastK || group.blocksRaycasts != open)
				{
					anim = Mathf.MoveTowards(anim, num, Time.unscaledDeltaTime / (open ? 0.18f : 0.12f));
					float num3 = 1f - (1f - anim) * (1f - anim);
					group.alpha = num3;
					((Transform)window).localScale = Vector3.one * num2 * (0.96f + 0.04f * num3);
					group.blocksRaycasts = open;
					lastK = num2;
					bool flag = anim != num;
					if (flag != tweening)
					{
						tweening = flag;
						if (flag)
						{
							UiTween.Begin();
						}
						else
						{
							UiTween.End();
						}
					}
				}
				if (!open && anim <= 0f && canvasGo.activeSelf)
				{
					canvasGo.SetActive(false);
				}
			}
			if (open && pendingSearchAt > 0f && Time.unscaledTime >= pendingSearchAt)
			{
				pendingSearchAt = -1f;
				ShowModule(activeModule);
			}
			if (open && fitDirty)
			{
				fitDirty = false;
				FitToCanvas();
			}
			if (open && pendingRows.Count > 0)
			{
				long timestamp = Stopwatch.GetTimestamp();
				long num4 = Stopwatch.Frequency / 1000;
				int childCount = ((Transform)listContent).childCount;
				while (pendingRows.Count > 0 && Stopwatch.GetTimestamp() - timestamp < num4)
				{
					pendingRows.Dequeue()();
				}
				for (int i = childCount; i < ((Transform)listContent).childCount; i++)
				{
					GildedUIModule.TypeNow(((Component)((Transform)listContent).GetChild(i)).gameObject);
				}
			}
			if (!open)
			{
				return;
			}
			bool adminView = F7Catalog.AdminView;
			bool staffView = F7Catalog.StaffView;
			if (adminView != lastAdminView || staffView != lastStaffView)
			{
				lastAdminView = adminView;
				lastStaffView = staffView;
				tabsDirty = true;
				dirty = true;
				if ((!staffView && activeModule == "Staff") || (!adminView && activeModule == "AdminSettings"))
				{
					activeModule = null;
				}
				ShowModule(activeModule ?? PageOf(F7Catalog.Group().SelectMany(((string cat, List<string> pages) g) => g.pages).FirstOrDefault()));
			}
			if ((Object)(object)ZNet.instance != (Object)null && (staffView || activeModule == "Staff"))
			{
				Staff.Tick();
			}
			if (staffDirty)
			{
				staffDirty = false;
				if (activeModule == "Staff")
				{
					TMP_InputField obj = search;
					if (string.IsNullOrEmpty((obj != null) ? obj.text : null))
					{
						ShowModule(activeModule);
					}
				}
			}
			if (tabsDirty)
			{
				BuildTabs();
				tabsDirty = false;
			}
			ForeignMods.FlushSaves(0.5f);
			if (dirty)
			{
				foreach (OptionRow row in rows)
				{
					if (Object.op_Implicit((Object)(object)row))
					{
						row.Refresh();
						row.RefreshLock();
					}
				}
				RefreshTabs();
				RefreshStatus();
				dirty = false;
			}
			Cursor.lockState = (CursorLockMode)0;
			Cursor.visible = true;
		}

		private bool InTextField()
		{
			EventSystem current = EventSystem.current;
			GameObject val = (((Object)(object)current != (Object)null) ? current.currentSelectedGameObject : null);
			if (!StringEditor.IsOpen && !((Object)(object)ClickActivate.Editing != (Object)null) && (!((Object)(object)val != (Object)null) || !((Object)(object)val.GetComponent<TMP_InputField>() != (Object)null) || !val.GetComponent<TMP_InputField>().isFocused) && !Console.IsVisible() && (!((Object)(object)Chat.instance != (Object)null) || !Chat.instance.HasFocus()))
			{
				return TextInput.IsVisible();
			}
			return true;
		}

		public void Toggle()
		{
			if ((Object)(object)canvasGo == (Object)null)
			{
				Build();
			}
			open = !open;
			if (open)
			{
				canvasGo.SetActive(true);
				FitToCanvas();
				UiTween.PanelOpened();
				GildedUIModule.TypeNow(canvasGo);
				if (activeModule == null)
				{
					activeModule = PageOf(Options.ModuleOrder.FirstOrDefault());
				}
				SetCollapsed(F7Catalog.Category(activeModule), v: false);
				BuildTabs();
				ShowModule(activeModule);
				RefreshStatus();
			}
			else
			{
				KeybindRow.Capturing = null;
				ShortcutRow.capturing = null;
				ForeignMods.FlushSaves();
				UITooltip.HideTooltip();
			}
		}

		private void LateUpdate()
		{
			if ((Object)(object)canvasGo == (Object)null || !canvasGo.activeSelf || (!typeDirty && !textRefit))
			{
				return;
			}
			bool flag = textRefit;
			textRefit = false;
			if (!(typeDirty || flag))
			{
				return;
			}
			typeDirty = false;
			if ((Object)(object)listContent != (Object)null)
			{
				GildedUIModule.TypeNow(((Component)listContent).gameObject);
			}
			if ((Object)(object)tabsContent != (Object)null)
			{
				GildedUIModule.TypeNow(((Component)tabsContent).gameObject);
			}
			RectTransform val = (RectTransform)(((Object)(object)listContent != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
			if ((Object)(object)val != (Object)null)
			{
				FlowJump(val);
			}
			if (!((Object)(object)listContent != (Object)null))
			{
				return;
			}
			((Component)listContent).GetComponentsInChildren<RowFit>(true, fitBuf);
			foreach (RowFit item in fitBuf)
			{
				if ((Object)(object)item != (Object)null)
				{
					item.Refit();
				}
			}
			fitBuf.Clear();
			LayoutRebuilder.MarkLayoutForRebuild(listContent);
		}

		public static void TextChanged()
		{
			textRefit = true;
		}

		private static void CloseGlyph(RectTransform close)
		{
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: 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_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_011e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: 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)
			Sprite val = (Gilded.Pref ? Gilded.Load("g3_close_64", 0f, 100f, mips: true) : null);
			Sprite val2 = (((Object)(object)val != (Object)null) ? Gilded.Load("g3_close_hover_64", 0f, 100f, mips: true) : null);
			if ((Object)(object)val != (Object)null)
			{
				RectTransform obj = Theme.Rect("XGlyph", (Transform)(object)close);
				Theme.Place(obj, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(24f, 24f));
				Image val3 = Theme.Img((Component)(object)obj, val, Color.white, sliced: false, raycast: false);
				((Graphic)val3).raycastTarget = false;
				val3.preserveAspect = true;
				CloseHover closeHover = ((Component)close).gameObject.AddComponent<CloseHover>();
				closeHover.Img = val3;
				closeHover.Normal = val;
				closeHover.Hover = val2 ?? val;
			}
			else
			{
				for (int i = 0; i < 2; i++)
				{
					RectTransform obj2 = Theme.Rect("X" + i, (Transform)(object)close);
					Theme.P