Decompiled source of ItemFavoriteFramework v1.0.0

plugins/ItemFavoriteFramework.dll

Decompiled 20 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
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.InteropServices;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using ItemFavoriteFramework.Common;
using Jotunn;
using Jotunn.Configs;
using Jotunn.Entities;
using Jotunn.Managers;
using Jotunn.Utils;
using SimpleJson;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
using YamlDotNet.Core;
using YamlDotNet.Core.Events;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ItemFavoriteFramework")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ItemFavoriteFramework")]
[assembly: AssemblyCopyright("Copyright ©  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
namespace ItemFavoriteFramework
{
	public static class API
	{
		public const int ApiVersion = 3;

		public const int MarkItemFavorite = 1;

		public const int MarkSlotFavorite = 2;

		public const int MarkTrash = 4;

		public const string MarkIdFavorite = "favorite";

		public const string MarkIdTrash = "trash";

		public const int RollPass = 1;

		public const int RollGreed = 2;

		public const int RollNeed = 3;

		public static int GetApiVersion()
		{
			return 3;
		}

		public static string GetPluginVersion()
		{
			return "1.0.0";
		}

		public static string GetPluginId()
		{
			return "MidnightsFX.ItemFavoriteFramework";
		}

		public static bool HasEndpoint(string name)
		{
			return GetEndpointNames().Contains(name);
		}

		public static List<string> GetEndpointNames()
		{
			return (from m in typeof(API).GetMethods(BindingFlags.Static | BindingFlags.Public)
				select m.Name).Distinct().OrderBy<string, string>((string n) => n, StringComparer.Ordinal).ToList();
		}

		public static bool IsReady()
		{
			MarkData result;
			return MarkStore.TryGet(out result);
		}

		public static bool IsItemFavorited(ItemData item)
		{
			return Marks.IsItemFavorited(item);
		}

		public static bool IsItemTrashFlagged(ItemData item)
		{
			return Marks.IsItemTrashFlagged(item);
		}

		public static bool IsSlotFavorited(int x, int y)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return Marks.IsSlotFavorited(new Vector2i(x, y));
		}

		public static bool IsItemInFavoritedSlot(ItemData item)
		{
			return Marks.IsItemInFavoritedSlot(item);
		}

		public static bool IsProtected(ItemData item)
		{
			return Marks.IsProtected(item);
		}

		public static int GetMarks(ItemData item)
		{
			return Marks.GetMarks(item);
		}

		public static List<ItemData> GetFavoritedItems(Inventory inventory)
		{
			return Marks.GetItems(inventory, Marks.IsItemFavorited);
		}

		public static List<ItemData> GetTrashFlaggedItems(Inventory inventory)
		{
			return Marks.GetItems(inventory, Marks.IsItemTrashFlagged);
		}

		public static List<ItemData> GetProtectedItems(Inventory inventory)
		{
			return Marks.GetItems(inventory, Marks.IsProtected);
		}

		public static List<Vector2i> GetFavoritedSlots()
		{
			if (!MarkStore.TryGet(out var result))
			{
				return new List<Vector2i>();
			}
			return (from s in result.Slots
				orderby s.y, s.x
				select s).ToList();
		}

		public static bool SetItemFavorited(ItemData item, bool favorited)
		{
			return Succeeded(Marks.SetItemFavorited(item, favorited));
		}

		public static bool SetItemTrashFlagged(ItemData item, bool trashFlagged)
		{
			return Succeeded(Marks.SetItemTrashFlagged(item, trashFlagged));
		}

		public static bool SetSlotFavorited(int x, int y, bool favorited)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return Succeeded(Marks.SetSlotFavorited(new Vector2i(x, y), favorited));
		}

		private static bool Succeeded(MarkResult result)
		{
			if (result != MarkResult.Changed)
			{
				return result == MarkResult.Unchanged;
			}
			return true;
		}

		public static void AddChangedListener(Action listener)
		{
			MarkStore.AddListener(listener);
		}

		public static void RemoveChangedListener(Action listener)
		{
			MarkStore.RemoveListener(listener);
		}

		public static Sprite GetFavoriteIcon()
		{
			return SpriteFactory.Star;
		}

		public static Sprite GetTrashIcon()
		{
			return SpriteFactory.Trash;
		}

		public static Color GetFavoriteColor()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return ValConfig.BorderColorFavoritedItem.Value;
		}

		public static Color GetFavoritedSlotColor()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return ValConfig.BorderColorFavoritedSlot.Value;
		}

		public static Color GetTrashColor()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return ValConfig.BorderColorTrashFlaggedItem.Value;
		}

		public static bool RegisterMarkType(string id, string group, Color color, Sprite icon, string tooltipToken)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			return CustomMarks.Register(id, group, color, icon, tooltipToken);
		}

		public static bool IsMarkTypeRegistered(string id)
		{
			return CustomMarks.IsRegistered(id);
		}

		public static bool HasCustomMark(ItemData item, string id)
		{
			return CustomMarks.Has(item, id);
		}

		public static List<string> GetCustomMarks(ItemData item)
		{
			return CustomMarks.Get(item);
		}

		public static bool SetCustomMark(ItemData item, string id, bool marked)
		{
			return CustomMarks.Set(item, id, marked);
		}

		public static void AddMarkListener(Action<ItemData, string, bool> listener)
		{
			MarkEvents.Add(listener);
		}

		public static void RemoveMarkListener(Action<ItemData, string, bool> listener)
		{
			MarkEvents.Remove(listener);
		}

		public static void AddItemClickHandler(Func<Inventory, ItemData, int, bool> handler)
		{
			ItemClickHandlers.Add(handler);
		}

		public static void RemoveItemClickHandler(Func<Inventory, ItemData, int, bool> handler)
		{
			ItemClickHandlers.Remove(handler);
		}

		public static bool IsItemWishlisted(ItemData item)
		{
			return Wishlists.IsWishlisted(item);
		}

		public static string GetWishlistJson()
		{
			WishlistStore.TryGet(out var result);
			return Wishlists.ToJson(result);
		}

		public static bool AddWishlistEntry(string prefabName, string criteriaJson)
		{
			if (!Wishlists.TryParseCriteria(criteriaJson, out var criteria))
			{
				return false;
			}
			WishResult wishResult = Wishlists.Add(prefabName, criteria, autoNeed: false);
			if (wishResult != WishResult.Added)
			{
				return wishResult == WishResult.Unchanged;
			}
			return true;
		}

		public static bool AddWishlistEntryFromItem(ItemData item)
		{
			WishResult wishResult = Wishlists.AddFromItem(item);
			if (wishResult != WishResult.Added)
			{
				return wishResult == WishResult.Unchanged;
			}
			return true;
		}

		public static int RemoveWishlistEntries(string prefabName)
		{
			return Wishlists.RemoveByPrefab(prefabName);
		}

		public static void AddWishlistChangedListener(Action listener)
		{
			WishlistStore.AddListener(listener);
		}

		public static void RemoveWishlistChangedListener(Action listener)
		{
			WishlistStore.RemoveListener(listener);
		}

		public static void OpenWishlistEditor()
		{
			WishlistPanel.Open();
		}

		public static bool RegisterWishlistProvider(string providerId, Func<string, string> getSchemaJson, Func<ItemData, string, bool> matches, Func<string, string> describe, Func<ItemData, string> suggest)
		{
			return WishlistProviders.Register(providerId, getSchemaJson, matches, describe, suggest);
		}

		public static bool UnregisterWishlistProvider(string providerId)
		{
			return WishlistProviders.Unregister(providerId);
		}

		public static Sprite GetWishlistIcon()
		{
			return SpriteFactory.Heart;
		}

		public static Color GetWishlistColor()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			return LootConfig.WishlistColor.Value;
		}

		public static void AddItemNameProvider(Func<ItemData, string> provider)
		{
			ItemNames.Add(provider);
		}

		public static void RemoveItemNameProvider(Func<ItemData, string> provider)
		{
			ItemNames.Remove(provider);
		}

		public static string GetServerFeaturesJson()
		{
			bool flag = (Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer();
			bool value = (flag ? LootConfig.EnableLootRolls.Value : ClientSession.RollsEnabled);
			bool value2 = (flag ? LootConfig.EnableWishlistSharing.Value : ClientSession.WishlistsEnabled);
			return new JsonBuilder().BeginObject().Bool("iff", flag || ClientSession.Welcomed).Num("protocol", 1L)
				.Str("version", flag ? "1.0.0" : ClientSession.ServerVersion)
				.Bool("rolls", value)
				.Bool("wishlists", value2)
				.Num("rollSeconds", flag ? LootConfig.RollSeconds.Value : ClientSession.RollSeconds)
				.Num("reserveSeconds", flag ? (LootConfig.ReserveMinutes.Value * 60f) : ClientSession.ReserveSeconds)
				.Num("maxMembers", flag ? LootConfig.MaxRollMembers.Value : ClientSession.MaxRollMembers)
				.EndObject()
				.ToString();
		}

		public static string GetConnectedPlayersJson()
		{
			JsonBuilder jsonBuilder = new JsonBuilder().BeginArray();
			if ((Object)(object)ZNet.instance != (Object)null && ZNet.instance.IsServer())
			{
				foreach (ServerPeer item in ServerSession.All)
				{
					if (item.Verified)
					{
						jsonBuilder.BeginObject().Id("player", item.Pid).Str("name", item.Name)
							.Bool("iff", item.HasIff)
							.Bool("sharesWishlist", item.SharesWishlist)
							.EndObject();
					}
				}
			}
			else
			{
				foreach (ClientSession.DirEntry item2 in ClientSession.Directory)
				{
					jsonBuilder.BeginObject().Id("player", item2.Pid).Str("name", item2.Name)
						.Bool("iff", item2.HasIff)
						.Bool("sharesWishlist", item2.Shares)
						.EndObject();
				}
			}
			return jsonBuilder.EndArray().ToString();
		}

		public static string GetPlayerWishlistJson(long playerId)
		{
			if (playerId != 0L && playerId == WishlistStore.PlayerId)
			{
				return GetWishlistJson();
			}
			WishlistRoster.Shared shared;
			return Wishlists.ToJson(WishlistRoster.TryGet(playerId, out shared) ? shared.Data : null);
		}

		public static string GetWantedByJson(ItemData item)
		{
			JsonBuilder jsonBuilder = new JsonBuilder().BeginArray();
			if (Wishlists.IsWishlisted(item))
			{
				jsonBuilder.BeginObject().Id("player", WishlistStore.PlayerId).Str("name", ((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerName() : "")
					.Bool("self", value: true)
					.EndObject();
			}
			foreach (long item2 in Wishlists.WantedBy(item))
			{
				jsonBuilder.BeginObject().Id("player", item2).Str("name", WishlistRoster.NameOf(item2))
					.Bool("self", value: false)
					.EndObject();
			}
			return jsonBuilder.EndArray().ToString();
		}

		public static bool IsRollingAvailable()
		{
			if ((Object)(object)ZNet.instance == (Object)null)
			{
				return false;
			}
			if (!ZNet.instance.IsServer())
			{
				return ClientSession.RollsEnabled;
			}
			return LootConfig.EnableLootRolls.Value;
		}

		public static bool StartRoll(ItemDrop drop, string playerIdsJson, string optionsJson, ref string rollId, ref string error)
		{
			string rollId2;
			string error2;
			bool result = RollClient.StartRoll(drop, Json.ParseIdList(playerIdsJson), optionsJson, out rollId2, out error2);
			rollId = rollId2;
			error = error2;
			return result;
		}

		public static bool StartRollForItem(ItemData item, Vector3 position, string playerIdsJson, string optionsJson, ref string rollId, ref string error)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			if (item == null || (Object)(object)item.m_dropPrefab == (Object)null)
			{
				rollId = "";
				error = "invalidItem";
				return false;
			}
			if (!IsRollingAvailable())
			{
				rollId = "";
				error = (((Object)(object)ZNet.instance == (Object)null) ? "notInWorld" : "disabled");
				return false;
			}
			ItemDrop val = ItemDrop.DropItem(item, item.m_stack, position, Quaternion.identity);
			if (StartRoll(val, playerIdsJson, optionsJson, ref rollId, ref error))
			{
				return true;
			}
			if ((Object)(object)val != (Object)null && (Object)(object)ZNetScene.instance != (Object)null)
			{
				ZNetScene.instance.Destroy(((Component)val).gameObject);
			}
			return false;
		}

		public static string GetRollStateJson(ItemDrop drop)
		{
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			JsonBuilder jsonBuilder = new JsonBuilder().BeginObject();
			ZDO val = (((Object)(object)drop != (Object)null && (Object)(object)drop.m_nview != (Object)null && drop.m_nview.IsValid()) ? drop.m_nview.GetZDO() : null);
			long num = RollStamp.ReadNonce(val);
			if (num == 0L)
			{
				return jsonBuilder.Str("phase", "free").EndObject().ToString();
			}
			LockState lockState = RollLocks.Resolve(val, RollLocks.LocalPid);
			jsonBuilder.Str("rollId", RollIds.Format(val.m_uid, num)).Str("phase", lockState switch
			{
				LockState.Free => "free", 
				LockState.Rolling => "rolling", 
				_ => "reserved", 
			});
			if (RollLocks.TryGetEntry(val.m_uid, out var entry) && entry.Nonce == num)
			{
				jsonBuilder.Id("winner", entry.WinnerPid).Str("winnerName", entry.WinnerName).Num("secondsLeft", RollLocks.SecondsLeft(val.m_uid));
			}
			return jsonBuilder.Bool("lockedForMe", lockState == LockState.Rolling || lockState == LockState.ReservedForOther).EndObject().ToString();
		}

		public static bool IsDropLocked(ItemDrop drop)
		{
			return RollLocks.Resolve(drop, 0L) != LockState.Free;
		}

		public static bool CanPlayerPickUp(ItemDrop drop, long playerId)
		{
			return !RollLocks.IsLockedFor(drop, playerId);
		}

		public static bool SubmitRollVote(string rollId, int choice)
		{
			if (choice < 1 || choice > 3)
			{
				return false;
			}
			return RollClient.Vote(rollId, (RollChoice)choice);
		}

		public static void AddRollListener(Action<string> listener)
		{
			RollEvents.Add(listener);
		}

		public static void RemoveRollListener(Action<string> listener)
		{
			RollEvents.Remove(listener);
		}

		public static string GetPlayerIdsNearJson(Vector3 point, float radius)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			return RollHelpers.ToJson(RollHelpers.PlayersNear(point, radius));
		}

		public static string GetDamagerPlayerIdsJson(Character character)
		{
			return RollHelpers.ToJson(RollHelpers.Damagers(character));
		}
	}
	internal static class ConfigFileWatcher
	{
		private class WatchEntry
		{
			internal DateTime LastWriteUTC;

			internal long FileLength;

			internal Action<string> Callback;
		}

		internal class ConfigFileWatcherBehaviour : MonoBehaviour
		{
			private float nextPollTime;

			public void Update()
			{
				if (!(Time.unscaledTime < nextPollTime))
				{
					nextPollTime = Time.unscaledTime + PollInterval();
					Poll();
				}
			}

			private static float PollInterval()
			{
				if (ValConfig.ConfigPollIntervalSeconds == null)
				{
					return 30f;
				}
				return ValConfig.ConfigPollIntervalSeconds.Value;
			}

			private static void Poll()
			{
				if (WatchedFiles.Count == 0)
				{
					return;
				}
				string[] array = WatchedFiles.Keys.ToArray();
				foreach (string text in array)
				{
					if (!WatchedFiles.TryGetValue(text, out var value) || !File.Exists(text))
					{
						continue;
					}
					FileInfo fileInfo = new FileInfo(text);
					DateTime lastWriteTimeUtc = fileInfo.LastWriteTimeUtc;
					long length = fileInfo.Length;
					if (!(lastWriteTimeUtc == value.LastWriteUTC) || length != value.FileLength)
					{
						value.LastWriteUTC = lastWriteTimeUtc;
						value.FileLength = length;
						try
						{
							value.Callback?.Invoke(text);
						}
						catch (Exception ex)
						{
							Logger.LogWarning("ConfigFileWatcher callback for " + text + " threw: " + ex.Message);
						}
					}
				}
			}
		}

		private const float FallbackPollSeconds = 30f;

		private static readonly Dictionary<string, WatchEntry> WatchedFiles = new Dictionary<string, WatchEntry>(StringComparer.OrdinalIgnoreCase);

		private static ConfigFileWatcherBehaviour watchProcess;

		internal static void Initialize()
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)watchProcess != (Object)null))
			{
				GameObject val = new GameObject("ItemFavoriteFramework_ConfigFileWatcher");
				Object.DontDestroyOnLoad((Object)val);
				((Object)val).hideFlags = (HideFlags)61;
				watchProcess = val.AddComponent<ConfigFileWatcherBehaviour>();
				Logger.LogDebug("ConfigFileWatcher initialized.");
			}
		}

		internal static void Register(string fullPath, Action<string> onChanged)
		{
			if (!string.IsNullOrEmpty(fullPath))
			{
				DateTime lastWriteUTC = DateTime.MinValue;
				long fileLength = 0L;
				if (File.Exists(fullPath))
				{
					FileInfo fileInfo = new FileInfo(fullPath);
					lastWriteUTC = fileInfo.LastWriteTimeUtc;
					fileLength = fileInfo.Length;
				}
				WatchedFiles[fullPath] = new WatchEntry
				{
					LastWriteUTC = lastWriteUTC,
					FileLength = fileLength,
					Callback = onChanged
				};
				Logger.LogDebug("ConfigFileWatcher watching " + fullPath);
			}
		}

		internal static void RefreshStamp(string fullPath)
		{
			if (string.IsNullOrEmpty(fullPath) || !WatchedFiles.TryGetValue(fullPath, out var value))
			{
				return;
			}
			try
			{
				FileInfo fileInfo = new FileInfo(fullPath);
				value.LastWriteUTC = fileInfo.LastWriteTimeUtc;
				value.FileLength = fileInfo.Length;
			}
			catch (Exception)
			{
				value.LastWriteUTC = DateTime.MinValue;
				value.FileLength = 0L;
			}
		}
	}
	internal static class ConfigNetwork
	{
		private static bool initialized;

		private static Harmony harmony;

		private static readonly HashSet<string> usedRpcNames = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

		private static readonly List<YamlConfigFile> editableFiles = new List<YamlConfigFile>();

		private static bool connectionPatchApplied;

		private const byte EditProtocolVersion = 1;

		private const int MaxEditRequestBytes = 250000;

		internal static bool ServerConfigsSynced { get; private set; }

		internal static event Action<YamlConfigFile, bool, string> EditResult;

		internal static void Init()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			if (initialized)
			{
				return;
			}
			initialized = true;
			SynchronizationManager.OnConfigurationSynchronized += OnConfigurationSynchronized;
			try
			{
				harmony = new Harmony("MidnightsFX.ItemFavoriteFramework.config");
				harmony.Patch((MethodBase)AccessTools.Method(typeof(ZNet), "Shutdown", (Type[])null, (Type[])null), new HarmonyMethod(typeof(ConfigNetwork), "ResetOnWorldUnload", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
			catch (Exception ex)
			{
				Logger.LogWarning("Could not patch ZNet.Shutdown for config sync teardown: " + ex.Message);
			}
		}

		internal static void RegisterFile(YamlConfigFile file)
		{
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Expected O, but got Unknown
			//IL_00ea: Expected O, but got Unknown
			if (file == null || file.Sync == ConfigSyncMode.LocalOnly)
			{
				return;
			}
			if (string.IsNullOrEmpty(file.RpcName))
			{
				file.RpcName = "ItemFavoriteFramework_" + Path.GetFileNameWithoutExtension(file.FileName);
			}
			if (!usedRpcNames.Add(file.RpcName))
			{
				Logger.LogError("Config RPC name '" + file.RpcName + "' is already in use; " + file.FileName + " will not be synced. Give it an explicit RpcName.");
				return;
			}
			file.Rpc = NetworkManager.Instance.AddRPC(file.RpcName, (CoroutineHandler)((long sender, ZPackage package) => OnServerReceive(file, sender, package)), (CoroutineHandler)((long sender, ZPackage package) => OnClientReceive(file, sender, package)));
			SynchronizationManager.Instance.AddInitialSynchronization(file.Rpc, (Func<ZPackage>)(() => SendFileAsZPackage(file)));
			if (!file.AllowAdminEdit)
			{
				return;
			}
			editableFiles.Add(file);
			PatchNewConnection();
			if (!((Object)(object)ZNet.instance != (Object)null))
			{
				return;
			}
			foreach (ZNetPeer peer in ZNet.instance.GetPeers())
			{
				RegisterEditRpcs(ZNet.instance, peer, file);
			}
		}

		private static void PatchNewConnection()
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Expected O, but got Unknown
			if (connectionPatchApplied)
			{
				return;
			}
			try
			{
				MethodInfo methodInfo = AccessTools.Method(typeof(ZNet), "OnNewConnection", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					Logger.LogError("ZNet.OnNewConnection not found; admins cannot edit server configs remotely.");
					return;
				}
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(ConfigNetwork), "RegisterConnectionRpcs", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				connectionPatchApplied = true;
			}
			catch (Exception ex)
			{
				Logger.LogError("Could not patch ZNet.OnNewConnection for admin config edits: " + ex.Message);
			}
		}

		private static void RegisterConnectionRpcs(ZNet __instance, ZNetPeer peer)
		{
			foreach (YamlConfigFile editableFile in editableFiles)
			{
				RegisterEditRpcs(__instance, peer, editableFile);
			}
		}

		private static void RegisterEditRpcs(ZNet znet, ZNetPeer peer, YamlConfigFile file)
		{
			if (znet.IsServer())
			{
				peer.m_rpc.Register<ZPackage>(EditRequestRpc(file), (Action<ZRpc, ZPackage>)delegate(ZRpc rpc, ZPackage package)
				{
					OnServerReceiveEdit(file, rpc, package);
				});
			}
			else
			{
				peer.m_rpc.Register<ZPackage>(EditResultRpc(file), (Action<ZRpc, ZPackage>)delegate(ZRpc rpc, ZPackage package)
				{
					OnClientReceiveEditResult(file, package);
				});
			}
		}

		private static string EditRequestRpc(YamlConfigFile file)
		{
			return "MidnightsFX.ItemFavoriteFramework." + file.RpcName + ".Edit";
		}

		private static string EditResultRpc(YamlConfigFile file)
		{
			return "MidnightsFX.ItemFavoriteFramework." + file.RpcName + ".EditResult";
		}

		internal static bool RequestEdit(YamlConfigFile file, string yaml, out string refusal)
		{
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Expected O, but got Unknown
			refusal = "";
			if (file == null || !editableFiles.Contains(file) || !connectionPatchApplied)
			{
				refusal = "this config cannot be edited remotely.";
				return false;
			}
			if ((Object)(object)ZNet.instance == (Object)null || ZNet.instance.IsServer())
			{
				refusal = "not connected to a server as a client.";
				return false;
			}
			if (SynchronizationManager.Instance != null && !SynchronizationManager.Instance.PlayerIsAdmin)
			{
				refusal = "only server admins can change this.";
				return false;
			}
			ZRpc serverRPC = ZNet.instance.GetServerRPC();
			if (serverRPC == null)
			{
				refusal = "not connected to a server as a client.";
				return false;
			}
			ZPackage val = new ZPackage();
			val.Write((byte)1);
			val.Write(yaml);
			if (val.Size() > 250000)
			{
				refusal = file.FileName + " is too large to send as an edit; change it on the server instead.";
				return false;
			}
			serverRPC.Invoke(EditRequestRpc(file), new object[1] { val });
			return true;
		}

		private static void OnServerReceiveEdit(YamlConfigFile file, ZRpc rpc, ZPackage package)
		{
			ZNetPeer peer = ZNet.instance.GetPeer(rpc);
			if (peer == null || !peer.IsReady())
			{
				return;
			}
			byte b = package.ReadByte();
			if (b != 1)
			{
				SendEditResult(peer, file, accepted: false, $"This server expects edit protocol v{(byte)1}, " + $"the sender used v{b}. Update so both sides match.");
				return;
			}
			string yaml = package.ReadString();
			string hostName = rpc.GetSocket().GetHostName();
			string message;
			if (!ZNet.instance.IsAdmin(hostName))
			{
				Logger.LogWarning("Rejecting an edit of " + file.FileName + " from non-admin " + peer.m_playerName + " (" + hostName + ").");
				SendEditResult(peer, file, accepted: false, "Only server admins can change " + file.FileName + ".");
			}
			else if (!YamlConfigManager.ApplyEdited(file, yaml, out message))
			{
				Logger.LogWarning("Admin " + peer.m_playerName + " (" + hostName + ") sent a " + file.FileName + " that was rejected: " + message);
				SendEditResult(peer, file, accepted: false, message);
			}
			else
			{
				Logger.LogInfo(file.FileName + " was replaced by admin " + peer.m_playerName + " (" + hostName + ").");
				SendEditResult(peer, file, accepted: true, message);
			}
		}

		private static void OnClientReceiveEditResult(YamlConfigFile file, ZPackage package)
		{
			if (package.ReadByte() != 1)
			{
				ConfigNetwork.EditResult?.Invoke(file, arg2: false, "The server answered with an edit protocol this build does not understand.");
				return;
			}
			bool arg = package.ReadBool();
			string arg2 = package.ReadString();
			ConfigNetwork.EditResult?.Invoke(file, arg, arg2);
		}

		private static void SendEditResult(ZNetPeer peer, YamlConfigFile file, bool accepted, string message)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			val.Write((byte)1);
			val.Write(accepted);
			val.Write(message ?? "");
			peer.m_rpc.Invoke(EditResultRpc(file), new object[1] { val });
		}

		internal static void Broadcast(YamlConfigFile file)
		{
			if (file != null && file.Rpc != null && !((Object)(object)ZNet.instance == (Object)null) && ZNet.instance.IsServer())
			{
				file.Rpc.SendPackage(ZNet.instance.m_peers, SendFileAsZPackage(file));
			}
		}

		internal static void ResetServerSyncState()
		{
			ServerConfigsSynced = false;
		}

		private static void OnConfigurationSynchronized(object sender, EventArgs e)
		{
			ServerConfigsSynced = true;
		}

		private static void ResetOnWorldUnload()
		{
			ResetServerSyncState();
		}

		private static IEnumerator OnServerReceive(YamlConfigFile file, long sender, ZPackage package)
		{
			Logger.LogDebug($"Peer {sender} sent {file.FileName}; this config is server-authoritative, ignoring.");
			yield break;
		}

		private static IEnumerator OnClientReceive(YamlConfigFile file, long sender, ZPackage package)
		{
			string text = package.ReadString();
			file.LoadFrom(text, ConfigOrigin.ServerSync);
			if (file.ClientWritesToDisk)
			{
				YamlConfigManager.WriteRawToDisk(file, text);
			}
			yield return null;
		}

		private static ZPackage SendFileAsZPackage(YamlConfigFile file)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Expected O, but got Unknown
			ZPackage val = new ZPackage();
			try
			{
				val.Write(File.Exists(file.Path) ? File.ReadAllText(file.Path) : file.SerializeCurrent());
			}
			catch (Exception ex)
			{
				Logger.LogError("Could not read " + file.FileName + " to send to peers: " + ex.Message);
				val.Write("");
			}
			return val;
		}
	}
	internal class ValidationReport
	{
		internal readonly List<string> Warnings = new List<string>();

		internal readonly List<string> Errors = new List<string>();

		internal bool HasErrors => Errors.Count > 0;

		internal ValidationReport Warn(string message)
		{
			Warnings.Add(message);
			return this;
		}

		internal ValidationReport Error(string message)
		{
			Errors.Add(message);
			return this;
		}

		internal ValidationReport Absorb(ValidationReport other)
		{
			if (other == null)
			{
				return this;
			}
			Warnings.AddRange(other.Warnings);
			Errors.AddRange(other.Errors);
			return this;
		}
	}
	internal static class ConfigValidation
	{
		internal static float Prefer(float bepInExValue, float yamlValue, float sentinel = 0f)
		{
			if (bepInExValue != sentinel)
			{
				return bepInExValue;
			}
			return yamlValue;
		}

		internal static string SuggestKey(string unknownKey, IEnumerable<string> knownKeys)
		{
			if (string.IsNullOrEmpty(unknownKey) || knownKeys == null)
			{
				return "";
			}
			int num = Math.Max(1, unknownKey.Length / 4);
			string text = null;
			int num2 = int.MaxValue;
			foreach (string knownKey in knownKeys)
			{
				if (!string.IsNullOrEmpty(knownKey))
				{
					int num3 = Distance(unknownKey, knownKey);
					if (num3 < num2)
					{
						num2 = num3;
						text = knownKey;
					}
				}
			}
			if (text == null || num2 > num)
			{
				return "";
			}
			return " Did you mean '" + text + "'?";
		}

		private static int Distance(string a, string b)
		{
			a = a.ToLowerInvariant();
			b = b.ToLowerInvariant();
			if (a == b)
			{
				return 0;
			}
			if (a.Length == 0)
			{
				return b.Length;
			}
			if (b.Length == 0)
			{
				return a.Length;
			}
			int[] array = new int[b.Length + 1];
			int[] array2 = new int[b.Length + 1];
			for (int i = 0; i <= b.Length; i++)
			{
				array[i] = i;
			}
			for (int j = 1; j <= a.Length; j++)
			{
				array2[0] = j;
				for (int k = 1; k <= b.Length; k++)
				{
					int num = ((a[j - 1] != b[k - 1]) ? 1 : 0);
					array2[k] = Math.Min(Math.Min(array2[k - 1] + 1, array[k] + 1), array[k - 1] + num);
				}
				int[] array3 = array;
				array = array2;
				array2 = array3;
			}
			return array[b.Length];
		}
	}
	internal static class YamlConfigManager
	{
		internal static YamlConfigFile<ExampleSettings> ExampleFile;

		internal static YamlConfigFile<Dictionary<string, int>> ExampleSavedDataFile;

		private const string ExampleHeader = "#################################################\n# ItemFavoriteFramework - Example settings\n#\n# Entries is a map of <key>: <entry>. The key is the identity used elsewhere in this mod, so\n# renaming one is a breaking change; DisplayName is only a label and is safe to change.\n#\n#   DisplayName  string   Shown to the player.\n#   Multiplier   float    Scales the thing. 1.0 is unchanged. Range 0.1 - 10.\n#   Mode         enum     Off | Add | Multiply\n#   Prefabs      list     Prefab names this entry applies to. Unknown names are warned about\n#                         and skipped, they do not break the file.\n#\n# A typo in a key or an enum value costs you that one setting and logs a warning naming the\n# line; the rest of the file still loads.\n#################################################";

		private static bool initialized;

		private static readonly List<YamlConfigFile> Files = new List<YamlConfigFile>();

		private static readonly Dictionary<string, YamlConfigFile> ByPath = new Dictionary<string, YamlConfigFile>(StringComparer.OrdinalIgnoreCase);

		internal static IEnumerable<YamlConfigFile> All => Files;

		private static void RegisterConfigFiles()
		{
			RegisterExampleConfigs();
		}

		private static void RegisterExampleConfigs()
		{
			ExampleFile = Register(new YamlConfigFile<ExampleSettings>("ExampleSettings.yaml")
			{
				Header = "#################################################\n# ItemFavoriteFramework - Example settings\n#\n# Entries is a map of <key>: <entry>. The key is the identity used elsewhere in this mod, so\n# renaming one is a breaking change; DisplayName is only a label and is safe to change.\n#\n#   DisplayName  string   Shown to the player.\n#   Multiplier   float    Scales the thing. 1.0 is unchanged. Range 0.1 - 10.\n#   Mode         enum     Off | Add | Multiply\n#   Prefabs      list     Prefab names this entry applies to. Unknown names are warned about\n#                         and skipped, they do not break the file.\n#\n# A typo in a key or an enum value costs you that one setting and logs a warning naming the\n# line; the rest of the file still loads.\n#################################################",
				Defaults = () => ExampleData.BuildDefaults(),
				Apply = delegate(ExampleSettings parsed)
				{
					ExampleData.Current = parsed;
				},
				Validate = ExampleData.Validate,
				NeedsPrefabs = true,
				SchemaVersion = 1,
				GetSchemaVersion = (ExampleSettings settings) => settings.Version,
				SetSchemaVersion = delegate(ExampleSettings settings, int version)
				{
					settings.Version = version;
				}
			});
			ExampleSavedDataFile = Register(new YamlConfigFile<Dictionary<string, int>>("ExampleSavedData.yaml")
			{
				SubFolder = "SavedData",
				Header = "# Save data written by this mod. Edit it with the game closed.",
				Defaults = () => new Dictionary<string, int>(),
				Apply = delegate(Dictionary<string, int> parsed)
				{
					ExampleData.SavedCounters = parsed;
				},
				Sync = ConfigSyncMode.LocalOnly,
				Watch = false
			});
			Register(new YamlConfigFile<Dictionary<string, ExampleEntry>>("ExampleLegacyFormat.yaml")
			{
				Header = "# A config kept in its original camelCase form for backwards compatibility.",
				Format = YamlFormat.CamelCase,
				Defaults = () => new Dictionary<string, ExampleEntry>(),
				Apply = delegate(Dictionary<string, ExampleEntry> parsed)
				{
					ExampleData.LegacyEntries = parsed;
				},
				ClientWritesToDisk = true
			});
		}

		internal static void Init()
		{
			if (!initialized)
			{
				initialized = true;
				ConfigNetwork.Init();
				YamlFormat.AddTypeConverter((IYamlTypeConverter)(object)new TolerantEnumConverter());
				RegisterConfigFiles();
				ConfigFileWatcher.Initialize();
				Logger.LogDebug($"Registered {Files.Count} yaml config files.");
			}
		}

		internal static TFile Register<TFile>(TFile file) where TFile : YamlConfigFile
		{
			if (file == null)
			{
				return null;
			}
			Files.Add(file);
			if (initialized)
			{
				Prepare(file);
			}
			return file;
		}

		internal static YamlConfigFile Find(string fileNameOrPath)
		{
			if (string.IsNullOrEmpty(fileNameOrPath))
			{
				return null;
			}
			if (ByPath.TryGetValue(fileNameOrPath, out var value))
			{
				return value;
			}
			for (int i = 0; i < Files.Count; i++)
			{
				if (string.Equals(Files[i].FileName, fileNameOrPath, StringComparison.OrdinalIgnoreCase))
				{
					return Files[i];
				}
			}
			return null;
		}

		internal static string ConfigDirectory(string subFolder = null)
		{
			string text = Path.Combine(Paths.ConfigPath, ValConfig.cfgFolder);
			if (!string.IsNullOrEmpty(subFolder))
			{
				text = Path.Combine(text, subFolder);
			}
			return Directory.CreateDirectory(text).FullName;
		}

		internal static void ReloadFromDisk(YamlConfigFile file, bool broadcast = true)
		{
			if (file == null)
			{
				return;
			}
			try
			{
				if (!File.Exists(file.Path))
				{
					Logger.LogWarning(file.FileName + " is no longer on disk; rewriting it with this mod's built-in defaults.");
					RestoreDefaults(file);
				}
				if (file.LoadFrom(File.ReadAllText(file.Path), ConfigOrigin.LocalFile) && broadcast)
				{
					ConfigNetwork.Broadcast(file);
				}
			}
			catch (Exception ex)
			{
				Logger.LogError("Could not reload " + file.FileName + ": " + ex.Message);
			}
		}

		internal static bool ApplyEdited(YamlConfigFile file, string yaml, out string message)
		{
			message = "";
			if (file == null)
			{
				message = "no config file was named";
				return false;
			}
			if ((Object)(object)ZNet.instance != (Object)null && !ZNet.instance.IsServer())
			{
				message = file.FileName + " belongs to the server; changes have to be sent to it.";
				return false;
			}
			string parseError;
			ValidationReport validationReport = file.DryRun(yaml, out parseError);
			if (parseError != null)
			{
				message = file.FileName + " was rejected because " + parseError + ".";
				return false;
			}
			if (validationReport.HasErrors)
			{
				message = string.Join(" ", validationReport.Errors.ToArray());
				return false;
			}
			if (!file.LoadFrom(yaml, ConfigOrigin.Api))
			{
				message = file.LastError ?? (file.FileName + " could not be applied.");
				return false;
			}
			WriteRawToDisk(file, yaml);
			ConfigNetwork.Broadcast(file);
			message = ((validationReport.Warnings.Count == 0) ? "" : string.Join(" ", validationReport.Warnings.ToArray()));
			return true;
		}

		internal static string SerializeForEdit<T>(YamlConfigFile<T> file, T value) where T : class
		{
			if (file == null || value == null)
			{
				return "";
			}
			return file.EffectiveFormat.Serializer.Serialize((object)value);
		}

		internal static void RestoreDefaults(YamlConfigFile file)
		{
			WriteRawToDisk(file, file?.SerializeDefaults());
		}

		internal static void WriteCurrentToDisk(YamlConfigFile file)
		{
			WriteRawToDisk(file, file?.SerializeCurrent());
		}

		internal static void WriteRawToDisk(YamlConfigFile file, string serializedYaml)
		{
			if (file == null || string.IsNullOrEmpty(file.Path))
			{
				return;
			}
			try
			{
				Directory.CreateDirectory(Path.GetDirectoryName(file.Path));
				using (StreamWriter streamWriter = new StreamWriter(file.Path))
				{
					if (!string.IsNullOrEmpty(file.Header))
					{
						streamWriter.WriteLine(file.Header);
					}
					streamWriter.WriteLine(serializedYaml);
				}
				ConfigFileWatcher.RefreshStamp(file.Path);
			}
			catch (Exception ex)
			{
				Logger.LogError("Could not write " + file.FileName + ": " + ex.Message);
			}
		}

		internal static void RevalidateAll()
		{
			for (int i = 0; i < Files.Count; i++)
			{
				try
				{
					Files[i].Revalidate();
				}
				catch (Exception ex)
				{
					Logger.LogError("Revalidating " + Files[i].FileName + " threw: " + ex.Message);
				}
			}
		}

		internal static bool HasNoUsableConfig(string yamlText)
		{
			if (string.IsNullOrWhiteSpace(yamlText))
			{
				return true;
			}
			string[] array = yamlText.Split(new char[1] { '\n' });
			for (int i = 0; i < array.Length; i++)
			{
				string text = array[i].Trim();
				if (text.Length != 0 && !text.StartsWith("#") && !(text == "---") && !(text == "..."))
				{
					return false;
				}
			}
			return true;
		}

		private static void Prepare(YamlConfigFile file)
		{
			try
			{
				file.Path = Path.Combine(ConfigDirectory(file.SubFolder), file.FileName);
				ByPath[file.Path] = file;
				if (!File.Exists(file.Path))
				{
					Logger.LogDebug(file.FileName + " missing, writing this mod's built-in defaults.");
					RestoreDefaults(file);
				}
				else if (HasNoUsableConfig(File.ReadAllText(file.Path)))
				{
					Logger.LogWarning(file.FileName + " was empty and has been overwritten with this mod's built-in defaults. File: " + file.Path);
					RestoreDefaults(file);
				}
				file.LoadFrom(File.Exists(file.Path) ? File.ReadAllText(file.Path) : "", ConfigOrigin.Startup);
				ConfigNetwork.RegisterFile(file);
				if (file.Watch)
				{
					ConfigFileWatcher.Register(file.Path, OnWatchedFileChanged);
				}
			}
			catch (Exception arg)
			{
				Logger.LogError($"Could not prepare {file.FileName}: {arg}");
			}
		}

		private static void OnWatchedFileChanged(string path)
		{
			if (ByPath.TryGetValue(path, out var file))
			{
				ConfigChangeDebouncer.Schedule(file, delegate
				{
					ReloadFromDisk(file);
				});
			}
		}
	}
	public enum ExampleMode
	{
		Off,
		Add,
		Multiply
	}
	public class ExampleEntry
	{
		public string DisplayName { get; set; }

		[DefaultValue(1f)]
		public float Multiplier { get; set; } = 1f;

		public ExampleMode Mode { get; set; }

		public List<string> Prefabs { get; set; } = new List<string>();
	}
	public class ExampleSettings
	{
		public int Version { get; set; } = 1;

		public Dictionary<string, ExampleEntry> Entries { get; set; } = new Dictionary<string, ExampleEntry>();
	}
	internal static class ExampleData
	{
		internal static ExampleSettings Current = new ExampleSettings();

		internal static Dictionary<string, int> SavedCounters = new Dictionary<string, int>();

		internal static Dictionary<string, ExampleEntry> LegacyEntries = new Dictionary<string, ExampleEntry>();

		internal static ExampleSettings BuildDefaults()
		{
			return new ExampleSettings
			{
				Version = 1,
				Entries = new Dictionary<string, ExampleEntry> { 
				{
					"Example",
					new ExampleEntry
					{
						DisplayName = "An example",
						Multiplier = 1.5f,
						Mode = ExampleMode.Multiply
					}
				} }
			};
		}

		internal static ValidationReport Validate(ExampleSettings next, ExampleSettings previous)
		{
			ValidationReport validationReport = new ValidationReport();
			if (next.Entries == null || next.Entries.Count == 0)
			{
				return validationReport.Error("it defines no entries");
			}
			foreach (KeyValuePair<string, ExampleEntry> entry in next.Entries)
			{
				if (entry.Value == null)
				{
					validationReport.Error("entry '" + entry.Key + "' has no settings under it");
					continue;
				}
				if (entry.Value.Multiplier < 0.1f || entry.Value.Multiplier > 10f)
				{
					validationReport.Warn($"entry '{entry.Key}' has Multiplier {entry.Value.Multiplier}, outside the " + "supported range of 0.1 - 10. It will be used as written.");
				}
				if (entry.Value.Prefabs == null)
				{
					continue;
				}
				foreach (string prefab in entry.Value.Prefabs)
				{
					if (PrefabManager.Instance != null && (Object)(object)PrefabManager.Instance.GetPrefab(prefab) == (Object)null)
					{
						validationReport.Warn("entry '" + entry.Key + "' names prefab '" + prefab + "', which does not exist. That prefab will be skipped.");
					}
				}
			}
			if (previous != null && previous.Entries != null)
			{
				foreach (string key in previous.Entries.Keys)
				{
					if (!next.Entries.ContainsKey(key))
					{
						validationReport.Warn("entry '" + key + "' was removed. Anything still referring to it will fall back.");
					}
				}
			}
			return validationReport;
		}
	}
	internal class TolerantEnumConverter : IYamlTypeConverter
	{
		private static readonly Dictionary<Type, object> fallbacks = new Dictionary<Type, object>();

		internal static void SetFallback(Type enumType, object fallback)
		{
			if (!(enumType == null) && enumType.IsEnum)
			{
				fallbacks[enumType] = fallback;
			}
		}

		public bool Accepts(Type type)
		{
			if (type != null)
			{
				return type.IsEnum;
			}
			return false;
		}

		public object ReadYaml(IParser parser, Type type, ObjectDeserializer rootDeserializer)
		{
			//IL_003e: 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)
			Scalar val = ParserExtensions.Consume<Scalar>(parser);
			string value = val.Value;
			if (!string.IsNullOrWhiteSpace(value))
			{
				try
				{
					return Enum.Parse(type, value.Trim(), ignoreCase: true);
				}
				catch (Exception)
				{
				}
			}
			object obj = FallbackFor(type);
			object[] array = new object[4];
			Mark start = ((ParsingEvent)val).Start;
			array[0] = ((Mark)(ref start)).Line;
			array[1] = value;
			array[2] = type.Name;
			array[3] = obj;
			Logger.LogWarning(string.Format("line {0}: '{1}' is not a valid {2}. Using {3}. ", array) + "Valid values: " + string.Join(", ", Enum.GetNames(type)) + ".");
			return obj;
		}

		public void WriteYaml(IEmitter emitter, object value, Type type, ObjectSerializer serializer)
		{
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			emitter.Emit((ParsingEvent)new Scalar((value == null) ? "" : value.ToString()));
		}

		private static object FallbackFor(Type type)
		{
			if (fallbacks.TryGetValue(type, out var value))
			{
				return value;
			}
			return Activator.CreateInstance(type);
		}
	}
	internal static class ConfigUI
	{
		internal class ConfigUIInputGuard : MonoBehaviour
		{
			private bool held;

			internal void Hold()
			{
				if (!held)
				{
					held = true;
					PushInputBlock();
				}
			}

			public void OnDestroy()
			{
				if (held)
				{
					held = false;
					PopInputBlock();
				}
			}
		}

		internal const float RowHeight = 34f;

		internal const float SubRowHeight = 26f;

		internal const float RowGap = 4f;

		internal const float CloseXSize = 28f;

		private static int inputBlockDepth;

		internal static void PushInputBlock()
		{
			if (!((Object)(object)Player.m_localPlayer == (Object)null))
			{
				inputBlockDepth++;
				if (inputBlockDepth == 1)
				{
					GUIManager.BlockInput(true);
				}
			}
		}

		internal static void PopInputBlock()
		{
			if (inputBlockDepth > 0)
			{
				inputBlockDepth--;
				if (inputBlockDepth == 0)
				{
					GUIManager.BlockInput(false);
				}
			}
		}

		internal static GameObject NewUI(string name, Transform parent, params Type[] components)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Expected O, but got Unknown
			GameObject val = new GameObject(name, components)
			{
				layer = 5
			};
			if ((Object)(object)val.GetComponent<RectTransform>() == (Object)null)
			{
				val.AddComponent<RectTransform>();
			}
			val.transform.SetParent(parent, false);
			return val;
		}

		internal static GameObject NewRect(string name, Transform parent, float x, float y, float w, float h)
		{
			//IL_0020: 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_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = NewUI(name, parent, typeof(RectTransform));
			RectTransform val = (RectTransform)obj.transform;
			val.anchorMin = new Vector2(0f, 1f);
			val.anchorMax = new Vector2(0f, 1f);
			val.pivot = new Vector2(0f, 1f);
			val.sizeDelta = new Vector2(w, h);
			val.anchoredPosition = new Vector2(x, 0f - y);
			return obj;
		}

		internal static GameObject NewRow(Transform parent, float width, float height)
		{
			return NewRect("Row", parent, 0f, 0f, width, height);
		}

		internal static GameObject NewLayoutRow(Transform content, float width, float height)
		{
			//IL_0031: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: 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)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = NewUI("LayoutRow", content, typeof(RectTransform), typeof(LayoutElement));
			RectTransform val = (RectTransform)obj.transform;
			val.anchorMin = new Vector2(0f, 1f);
			val.anchorMax = new Vector2(0f, 1f);
			val.pivot = new Vector2(0f, 1f);
			val.sizeDelta = new Vector2(width, height);
			LayoutElement component = obj.GetComponent<LayoutElement>();
			component.minHeight = height;
			component.preferredHeight = height;
			component.minWidth = width;
			component.preferredWidth = width;
			return obj;
		}

		internal static void LayoutColumn(List<GameObject> rows, float x, float startY, float gap = 4f)
		{
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected O, but got Unknown
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			float num = startY;
			foreach (GameObject row in rows)
			{
				if (!((Object)(object)row == (Object)null) && row.activeSelf)
				{
					RectTransform val = (RectTransform)row.transform;
					val.anchoredPosition = new Vector2(x, 0f - num);
					num += val.sizeDelta.y + gap;
				}
			}
		}

		internal static void PositionRow(GameObject row, float x, float y)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)row == (Object)null))
			{
				((RectTransform)row.transform).anchoredPosition = new Vector2(x, 0f - y);
			}
		}

		internal static GameObject CreatePanel(string title, float w, float h, out Transform body)
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GUIManager.Instance.CreateWoodpanel(GUIManager.CustomGUIFront.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), w, h, true);
			val.AddComponent<ConfigUIInputGuard>().Hold();
			AddText(val.transform, 0f, 16f, w, 34f, title, 22, (TextAnchor)4, GUIManager.Instance.ValheimYellow);
			body = val.transform;
			return val;
		}

		internal static GameObject CreateScroll(Transform parent, float x, float y, float w, float h, out Transform content, out float contentWidth)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = NewRect("ScrollHolder", parent, x, y, w, h);
			GameObject val2 = GUIManager.Instance.CreateScrollView(val.transform, false, true, 8f, 4f, GUIManager.Instance.ValheimScrollbarHandleColorBlock, new Color(0f, 0f, 0f, 0.5f), w, h);
			content = val2.transform.Find("Scroll View/Viewport/Content");
			contentWidth = w - 16f;
			ScrollRect componentInChildren = val2.GetComponentInChildren<ScrollRect>();
			if ((Object)(object)componentInChildren != (Object)null)
			{
				componentInChildren.scrollSensitivity = 200f;
			}
			return val2;
		}

		internal static string L(string text)
		{
			if (string.IsNullOrEmpty(text))
			{
				return "";
			}
			if (Localization.instance == null)
			{
				return text;
			}
			return Localization.instance.Localize(text);
		}

		internal static string L(string token, string english)
		{
			string text = L(token);
			if (text.Length == 0 || text == token || text == "[" + token.TrimStart(new char[1] { '$' }) + "]")
			{
				return english;
			}
			return text;
		}

		internal static Text AddText(Transform parent, float x, float y, float w, float h, string text, int fontSize, TextAnchor anchor, Color? color = null)
		{
			//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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//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_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GUIManager.Instance.CreateText(L(text), parent, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(x, 0f - y), GUIManager.Instance.AveriaSerifBold, fontSize, (Color)(((??)color) ?? GUIManager.Instance.ValheimBeige), true, Color.black, w, h, false);
			RectTransform val = (RectTransform)obj.transform;
			val.pivot = new Vector2(0f, 1f);
			val.anchoredPosition = new Vector2(x, 0f - y);
			Text component = obj.GetComponent<Text>();
			component.alignment = anchor;
			component.horizontalOverflow = (HorizontalWrapMode)0;
			component.verticalOverflow = (VerticalWrapMode)0;
			return component;
		}

		internal static GameObject AddHeaderRow(Transform parent, float colWidth, string text, TextAnchor anchor = (TextAnchor)3)
		{
			//IL_0025: 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)
			GameObject obj = NewRow(parent, colWidth, 34f);
			AddText(obj.transform, 0f, 0f, colWidth, 34f, text, 18, anchor, GUIManager.Instance.ValheimYellow);
			return obj;
		}

		internal static GameObject AddTextRow(Transform parent, float colWidth, float height, string text, int fontSize, Color color, TextAnchor anchor = (TextAnchor)0)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = NewRow(parent, colWidth, height);
			AddText(obj.transform, 0f, 0f, colWidth, height, text, fontSize, anchor, color);
			return obj;
		}

		internal static GameObject AddSpacerRow(Transform parent, float colWidth, float height)
		{
			return NewRow(parent, colWidth, height);
		}

		internal static GameObject AddDividerRow(Transform parent, float colWidth, float height = 12f)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = NewRow(parent, colWidth, height);
			GameObject obj = NewUI("Divider", val.transform, typeof(Image));
			RectTransform val2 = (RectTransform)obj.transform;
			val2.anchorMin = new Vector2(0f, 1f);
			val2.anchorMax = new Vector2(0f, 1f);
			val2.pivot = new Vector2(0f, 1f);
			val2.sizeDelta = new Vector2(colWidth, 2f);
			val2.anchoredPosition = new Vector2(0f, 0f - height * 0.5f);
			Image component = obj.GetComponent<Image>();
			((Graphic)component).color = new Color(0.6f, 0.5f, 0.35f, 0.6f);
			((Graphic)component).raycastTarget = false;
			return val;
		}

		internal static void SetMessages(Text target, IList<string> errors, IList<string> warnings)
		{
			if ((Object)(object)target == (Object)null)
			{
				return;
			}
			List<string> list = new List<string>();
			if (errors != null)
			{
				foreach (string error in errors)
				{
					list.Add("<color=#F87171>" + error + "</color>");
				}
			}
			if (warnings != null)
			{
				foreach (string warning in warnings)
				{
					list.Add("<color=#FBBF24>" + warning + "</color>");
				}
			}
			target.text = string.Join("\n", list.ToArray());
		}

		internal static GameObject AddButton(Transform parent, float x, float y, float w, string text, UnityAction onClick, float h = 40f)
		{
			//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_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = GUIManager.Instance.CreateButton(L(text), parent, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(x, 0f - y), w, h);
			RectTransform val2 = (RectTransform)val.transform;
			val2.pivot = new Vector2(0f, 1f);
			val2.anchoredPosition = new Vector2(x, 0f - y);
			if (onClick != null)
			{
				((UnityEvent)val.GetComponent<Button>().onClick).AddListener(onClick);
			}
			return val;
		}

		internal static GameObject AddCloseX(Transform panel, float panelWidth, UnityAction onClick)
		{
			return AddButton(panel, panelWidth - 28f - 16f, 12f, 28f, "X", onClick, 28f);
		}

		internal static Toggle AddToggle(Transform parent, float x, float y, float size, bool value, Action<bool> onChange)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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)
			//IL_0068: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			GameObject obj = GUIManager.Instance.CreateToggle(parent, size, size);
			obj.transform.SetParent(parent, false);
			RectTransform val = (RectTransform)obj.transform;
			((Transform)val).localScale = Vector3.one;
			val.anchorMin = new Vector2(0f, 1f);
			val.anchorMax = new Vector2(0f, 1f);
			val.pivot = new Vector2(0f, 1f);
			val.anchoredPosition = new Vector2(x, 0f - y);
			Toggle component = obj.GetComponent<Toggle>();
			component.isOn = value;
			if (onChange != null)
			{
				((UnityEvent<bool>)(object)component.onValueChanged).AddListener((UnityAction<bool>)delegate(bool b)
				{
					onChange(b);
				});
			}
			return component;
		}

		internal static GameObject AddToggleRow(Transform parent, float colWidth, float labelW, string label, bool value, Action<bool> onChange, bool toggleOnLeft = false)
		{
			GameObject obj = NewRow(parent, colWidth, 34f);
			float x = (toggleOnLeft ? 0f : (labelW + 6f));
			float x2 = (toggleOnLeft ? 34f : 0f);
			AddText(obj.transform, x2, 0f, labelW, 34f, label, 15, (TextAnchor)3);
			AddToggle(obj.transform, x, 3f, 26f, value, onChange);
			return obj;
		}

		internal static string Fmt(float v, bool whole)
		{
			if (!whole)
			{
				return v.ToString("0.00", CultureInfo.InvariantCulture);
			}
			return ((int)Mathf.Round(v)).ToString(CultureInfo.InvariantCulture);
		}

		internal static Slider BuildSlider(Transform parent, float x, float y, float width, float min, float max, float value, bool wholeNumbers)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_0173: Unknown result type (might be due to invalid IL or missing references)
			//IL_017d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0192: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Expected O, but got Unknown
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_022d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0232: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0248: Unknown result type (might be due to invalid IL or missing references)
			//IL_0253: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0290: Unknown result type (might be due to invalid IL or missing references)
			//IL_0297: Expected O, but got Unknown
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = NewUI("Slider", parent, typeof(RectTransform), typeof(Slider));
			RectTransform val2 = (RectTransform)val.transform;
			val2.anchorMin = new Vector2(0f, 1f);
			val2.anchorMax = new Vector2(0f, 1f);
			val2.pivot = new Vector2(0f, 1f);
			val2.sizeDelta = new Vector2(width, 20f);
			val2.anchoredPosition = new Vector2(x, 0f - y);
			GameObject obj = NewUI("Background", val.transform, typeof(Image));
			RectTransform val3 = (RectTransform)obj.transform;
			val3.anchorMin = new Vector2(0f, 0.25f);
			val3.anchorMax = new Vector2(1f, 0.75f);
			val3.sizeDelta = Vector2.zero;
			val3.anchoredPosition = Vector2.zero;
			((Graphic)obj.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.6f);
			GameObject val4 = NewUI("Fill Area", val.transform, typeof(RectTransform));
			RectTransform val5 = (RectTransform)val4.transform;
			val5.anchorMin = new Vector2(0f, 0.25f);
			val5.anchorMax = new Vector2(1f, 0.75f);
			val5.sizeDelta = new Vector2(-20f, 0f);
			val5.anchoredPosition = Vector2.zero;
			GameObject obj2 = NewUI("Fill", val4.transform, typeof(Image));
			RectTransform val6 = (RectTransform)obj2.transform;
			val6.sizeDelta = new Vector2(10f, 0f);
			((Graphic)obj2.GetComponent<Image>()).color = new Color(0.7f, 0.6f, 0.4f, 0.9f);
			GameObject val7 = NewUI("Handle Slide Area", val.transform, typeof(RectTransform));
			RectTransform val8 = (RectTransform)val7.transform;
			val8.anchorMin = Vector2.zero;
			val8.anchorMax = Vector2.one;
			val8.sizeDelta = new Vector2(-20f, 0f);
			val8.anchoredPosition = Vector2.zero;
			GameObject obj3 = NewUI("Handle", val7.transform, typeof(Image));
			RectTransform val9 = (RectTransform)obj3.transform;
			val9.sizeDelta = new Vector2(20f, 0f);
			Image component = obj3.GetComponent<Image>();
			component.sprite = GUIManager.Instance.GetSprite("checkbox_marker");
			component.type = (Type)1;
			Slider component2 = val.GetComponent<Slider>();
			component2.fillRect = val6;
			component2.handleRect = val9;
			((Selectable)component2).targetGraphic = (Graphic)(object)component;
			component2.direction = (Direction)0;
			component2.minValue = min;
			component2.maxValue = max;
			component2.wholeNumbers = wholeNumbers;
			component2.value = Mathf.Clamp(value, min, max);
			GUIManager.Instance.ApplySliderStyle(component2);
			return component2;
		}

		internal static GameObject AddSliderRow(Transform parent, float colWidth, float labelW, float sliderW, float valueW, string label, float min, float max, float value, bool wholeNumbers, Action<float> onChange)
		{
			//IL_00a9: 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_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = NewRow(parent, colWidth, 34f);
			AddText(val.transform, 0f, 0f, labelW, 34f, label, 15, (TextAnchor)3);
			Slider slider = BuildSlider(val.transform, labelW, 7f, sliderW, min, max, value, wholeNumbers);
			float num = labelW + sliderW + 10f;
			GameObject val2 = GUIManager.Instance.CreateInputField(val.transform, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(num, -3f), (ContentType)(wholeNumbers ? 2 : 3), (string)null, 15, valueW, 28f);
			RectTransform val3 = (RectTransform)val2.transform;
			val3.pivot = new Vector2(0f, 1f);
			val3.anchoredPosition = new Vector2(num, -3f);
			InputField box = val2.GetComponent<InputField>();
			box.SetTextWithoutNotify(Fmt(slider.value, wholeNumbers));
			((UnityEvent<float>)(object)slider.onValueChanged).AddListener((UnityAction<float>)delegate(float v)
			{
				if (wholeNumbers)
				{
					v = Mathf.Round(v);
				}
				box.SetTextWithoutNotify(Fmt(v, wholeNumbers));
				onChange?.Invoke(v);
			});
			((UnityEvent<string>)(object)box.onEndEdit).AddListener((UnityAction<string>)delegate(string str)
			{
				if (!float.TryParse(str.Replace(',', '.'), NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
				{
					result = slider.value;
				}
				result = Mathf.Clamp(result, min, max);
				if (wholeNumbers)
				{
					result = Mathf.Round(result);
				}
				box.SetTextWithoutNotify(Fmt(result, wholeNumbers));
				if (slider.value != result)
				{
					slider.value = result;
				}
				else
				{
					onChange?.Invoke(result);
				}
			});
			return val;
		}

		internal static InputField AddTextField(Transform parent, float x, float y, float w, string value, Action<string> onCommit, ContentType contentType = (ContentType)0, string placeholder = null, int charLimit = 0)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_003a: 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)
			//IL_0056: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: 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)
			GameObject obj = GUIManager.Instance.CreateInputField(parent, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(x, 0f - y), contentType, placeholder, 15, w, 28f);
			RectTransform val = (RectTransform)obj.transform;
			val.pivot = new Vector2(0f, 1f);
			val.anchoredPosition = new Vector2(x, 0f - y);
			InputField component = obj.GetComponent<InputField>();
			if (charLimit > 0)
			{
				component.characterLimit = charLimit;
			}
			component.SetTextWithoutNotify(value ?? "");
			if (onCommit != null)
			{
				((UnityEvent<string>)(object)component.onEndEdit).AddListener((UnityAction<string>)delegate(string s)
				{
					onCommit(s);
				});
			}
			return component;
		}

		internal static GameObject AddTextFieldRow(Transform parent, float colWidth, float labelW, float fieldW, string label, string value, Action<string> onCommit, string placeholder = null, int charLimit = 0)
		{
			GameObject obj = NewRow(parent, colWidth, 34f);
			AddText(obj.transform, 0f, 0f, labelW, 34f, label, 15, (TextAnchor)3);
			AddTextField(obj.transform, labelW + 6f, 3f, fieldW, value, onCommit, (ContentType)0, placeholder, charLimit);
			return obj;
		}

		internal static GameObject AddEnumCycleRow(Transform parent, float colWidth, float labelW, float ctrlW, string label, string[] options, int currentIndex, Action<int> onChange)
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: 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_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Expected O, but got Unknown
			GameObject val = NewRow(parent, colWidth, 34f);
			AddText(val.transform, 0f, 0f, labelW, 34f, label, 15, (TextAnchor)3);
			int idx = Mathf.Clamp(currentIndex, 0, Math.Max(0, options.Length - 1));
			GameObject val2 = GUIManager.Instance.CreateButton((options.Length != 0) ? options[idx] : "", val.transform, new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(labelW + 6f, -2f), ctrlW, 28f);
			RectTransform val3 = (RectTransform)val2.transform;
			val3.pivot = new Vector2(0f, 1f);
			val3.anchoredPosition = new Vector2(labelW + 6f, -2f);
			Text caption = val2.GetComponentInChildren<Text>();
			((UnityEvent)val2.GetComponent<Button>().onClick).AddListener((UnityAction)delegate
			{
				if (options.Length != 0)
				{
					idx = (idx + 1) % options.Length;
					caption.text = options[idx];
					onChange?.Invoke(idx);
				}
			});
			return val;
		}

		internal static GameObject AddEnumFlagsRow(Transform parent, float colWidth, float labelW, string label, string[] names, Func<int, bool> isOn, Action<int, bool> set)
		{
			GameObject val = NewRow(parent, colWidth, 34f);
			AddText(val.transform, 0f, 0f, labelW, 34f, label, 15, (TextAnchor)3);
			float num = labelW + 6f;
			for (int i = 0; i < names.Length; i++)
			{
				int index = i;
				AddToggle(val.transform, num, 4f, 22f, isOn(index), delegate(bool on)
				{
					set(index, on);
				});
				AddText(val.transform, num + 26f, 0f, 90f, 34f, names[index], 13, (TextAnchor)3);
				num += 120f;
			}
			return val;
		}

		internal static GameObject AddPickerRow(Transform parent, float colWidth, float labelW, float ctrlW, string label, string current, Func<IList<string>> options, Action<string> onPick, Func<string, bool> isKnown = null)
		{
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Expected O, but got Unknown
			GameObject val = NewRow(parent, colWidth, 34f);
			AddText(val.transform, 0f, 0f, labelW, 34f, label, 15, (TextAnchor)3);
			float num = ctrlW - 40f;
			InputField field = AddTextField(val.transform, labelW + 6f, 3f, num, current, delegate(string s)
			{
				onPick?.Invoke(s);
			}, (ContentType)0);
			Text marker = AddText(val.transform, labelW + 6f + num + 44f, 0f, 20f, 34f, "", 15, (TextAnchor)3, (Color?)new Color(0.98f, 0.75f, 0.14f));
			Action refreshMarker = delegate
			{
				bool flag = isKnown != null && !string.IsNullOrEmpty(field.text) && !isKnown(field.text);
				marker.text = (flag ? "!" : "");
			};
			refreshMarker();
			((UnityEvent<string>)(object)field.onEndEdit).AddListener((UnityAction<string>)delegate
			{
				refreshMarker();
			});
			AddButton(val.transform, labelW + 6f + num + 4f, 3f, 34f, "...", (UnityAction)delegate
			{
				string title = label;
				IList<string> options2;
				if (options == null)
				{
					IList<string> list = new List<string>();
					options2 = list;
				}
				else
				{
					options2 = options();
				}
				ConfigUIPicker.ShowPicker(title, options2, field.text, delegate(string picked)
				{
					field.SetTextWithoutNotify(picked);
					refreshMarker();
					onPick?.Invoke(picked);
				});
			}, 28f);
			return val;
		}

		internal static GameObject AddStringListEditor(Transform content, float width, string label, List<string> items, Action onChanged, Func<IList<string>> options = null, Func<string, bool> isKnown = null)
		{
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Expected O, but got Unknown
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Expected O, but got Unknown
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e3: Expected O, but got Unknown
			GameObject val = NewLayoutRow(content, width, 26f);
			AddText(val.transform, 0f, 0f, width - 90f, 26f, label, 14, (TextAnchor)3, GUIManager.Instance.ValheimOrange);
			AddButton(val.transform, width - 84f, 0f, 80f, L("$piece_smelter_add", "Add"), (UnityAction)delegate
			{
				items.Add("");
				onChanged?.Invoke();
			}, 24f);
			for (int num = 0; num < items.Count; num++)
			{
				int index = num;
				GameObject val2 = NewLayoutRow(content, width, 26f);
				InputField field = AddTextField(val2.transform, 12f, 0f, width - 92f, items[index], delegate(string s)
				{
					items[index] = s;
				}, (ContentType)0);
				Text marker = AddText(val2.transform, width - 74f, 0f, 16f, 26f, "", 14, (TextAnchor)3, (Color?)new Color(0.98f, 0.75f, 0.14f));
				Action refreshMarker = delegate
				{
					bool flag = isKnown != null && !string.IsNullOrEmpty(field.text) && !isKnown(field.text);
					marker.text = (flag ? "!" : "");
				};
				refreshMarker();
				((UnityEvent<string>)(object)field.onEndEdit).AddListener((UnityAction<string>)delegate
				{
					refreshMarker();
				});
				if (options != null)
				{
					AddButton(val2.transform, width - 56f, 0f, 26f, "...", (UnityAction)delegate
					{
						ConfigUIPicker.ShowPicker(label, options(), field.text, delegate(string picked)
						{
							field.SetTextWithoutNotify(picked);
							items[index] = picked;
							refreshMarker();
						});
					}, 24f);
				}
				AddButton(val2.transform, width - 26f, 0f, 24f, "x", (UnityAction)delegate
				{
					items.RemoveAt(index);
					onChanged?.Invoke();
				}, 24f);
			}
			return val;
		}
	}
	internal enum FirstRunMode
	{
		Auto,
		ShowNextLaunch,
		Never
	}
	internal static class ConfigUIFirstRun
	{
		internal const string FolderName = "ModQuickConfig";

		internal const string FileName = "FirstRun.cfg";

		internal const string Section = "FirstRun";

		internal const string QueueKeySuffix = ".FirstRun";

		private const string LegacyPlaceholder = "\u0001";

		private static string recordPath;

		private static readonly char[] InvalidKeyChars = new char[8] { '=', '\n', '\t', '\\', '"', '\'', '[', ']' };

		internal static string RecordPath
		{
			get
			{
				if (recordPath == null)
				{
					recordPath = Path.Combine(Path.Combine(Application.persistentDataPath, "ModQuickConfig"), "FirstRun.cfg");
				}
				return recordPath;
			}
		}

		internal static bool ShouldShow(string modKey, int revision, ConfigEntry<FirstRunMode> mode)
		{
			if (GUIManager.IsHeadless())
			{
				return false;
			}
			return ModeOf(mode) switch
			{
				FirstRunMode.Never => false, 
				FirstRunMode.ShowNextLaunch => true, 
				_ => SeenRevision(modKey) < revision, 
			};
		}

		internal static int SeenRevision(string modKey)
		{
			if (GUIManager.IsHeadless() || !IsValidKey(modKey))
			{
				return int.MaxValue;
			}
			string text = null;
			try
			{
				text = RecordPath;
				if (!File.Exists(text))
				{
					return 0;
				}
				return Math.Max(0, BindSeen(OpenRecord(), modKey).Value);
			}
			catch (Exception ex)
			{
				Logger.LogWarning("Could not read the first-run record at " + text + ", so the '" + modKey + "' first-run popup is treated as seen: " + ex.Message);
				return int.MaxValue;
			}
		}

		internal static void MarkSeen(string modKey, int revision)
		{
			if (GUIManager.IsHeadless() || !IsValidKey(modKey) || revision <= 0)
			{
				return;
			}
			string text = null;
			try
			{
				text = RecordPath;
				ConfigFile val = OpenRecord();
				ConfigEntry<int> val2 = BindSeen(val, modKey);
				if (val2.Value < revision)
				{
					val2.Value = revision;
					val.Save();
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning("Could not write the first-run record at " + text + ": " + ex.Message);
			}
		}

		internal static bool QueueFirstRunPopup(string modKey, int revision, ConfigEntry<FirstRunMode> mode, int order, Func<bool> open, Func<bool> isOpen)
		{
			if (open == null || isOpen == null || !ShouldShow(modKey, revision, mode))
			{
				return false;
			}
			return ConfigUIStartupPopups.Enqueue(modKey + ".FirstRun", order, () => OpenFirstRun(modKey, revision, mode, open), isOpen);
		}

		private static bool OpenFirstRun(string modKey, int revision, ConfigEntry<FirstRunMode> mode, Func<bool> open)
		{
			if (!ShouldShow(modKey, revision, mode))
			{
				return false;
			}
			bool flag = false;
			if (mode != null && mode.Value == FirstRunMode.ShowNextLaunch)
			{
				mode.Value = FirstRunMode.Auto;
				flag = true;
			}
			bool flag2 = false;
			try
			{
				flag2 = open();
			}
			finally
			{
				if (!flag2 && flag)
				{
					mode.Value = FirstRunMode.ShowNextLaunch;
				}
			}
			return flag2;
		}

		internal static bool TakeLegacyEntry(ConfigFile cfg, string section, string key, out string raw)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Expected O, but got Unknown
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			raw = null;
			if (cfg == null || string.IsNullOrEmpty(section) || string.IsNullOrEmpty(key))
			{
				return false;
			}
			bool saveOnConfigSet = cfg.SaveOnConfigSet;
			cfg.SaveOnConfigSet = false;
			try
			{
				ConfigDefinition val = new ConfigDefinition(section, key);
				if (cfg.ContainsKey(val))
				{
					raw = cfg[val].GetSerializedValue();
				}
				else
				{
					string value = cfg.Bind<string>(val, "\u0001", new ConfigDescription("Retired.", (AcceptableValueBase)null, Array.Empty<object>())).Value;
					raw = ((value == "\u0001") ? null : value);
				}
				cfg.Remove(val);
				if (saveOnConfigSet)
				{
					cfg.Save();
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning("Could not read the retired setting [" + section + "] " + key + ": " + ex.Message);
				raw = null;
			}
			finally
			{
				cfg.SaveOnConfigSet = saveOnConfigSet;
			}
			return raw != null;
		}

		private static ConfigFile OpenRecord()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			BepInPlugin val = new BepInPlugin("ModQuickConfig.FirstRun", "ModQuickConfig first-run record - delete this file to see every mod's first-run popup again", "1.0.0");
			return new ConfigFile(RecordPath, false, val)
			{
				SaveOnConfigSet = false
			};
		}

		private static ConfigEntry<int> BindSeen(ConfigFile record, string modKey)
		{
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Expected O, but got Unknown
			return record.Bind<int>("FirstRun", modKey, 0, new ConfigDescription("The newest revision of this mod's first-run popup you have seen. 0 has not seen it; delete the line to see it again.", (AcceptableValueBase)null, Array.Empty<object>()));
		}

		private static FirstRunMode ModeOf(ConfigEntry<FirstRunMode> mode)
		{
			if (mode == null)
			{
				return FirstRunMode.Auto;
			}
			FirstRunMode value = mode.Value;
			if (!Enum.IsDefined(typeof(FirstRunMode), value))
			{
				return FirstRunMode.Auto;
			}
			return value;
		}

		private static bool IsValidKey(string modKey)
		{
			if (string.IsNullOrEmpty(modKey) || modKey.Trim() != modKey || modKey.IndexOfAny(InvalidKeyChars) >= 0)
			{
				Logger.LogError("'" + modKey + "' cannot be a first-run record key; use a plain identifier.");
				return false;
			}
			return true;
		}
	}
	internal static class ConfigUILauncher
	{
		private static Component cachedBroker;

		private static MethodInfo cachedRegister;

		private static MethodInfo cachedUnregister;

		private static bool loggedOwner;

		internal static bool IsAvailable => (Object)(object)Resolve() != (Object)null;

		internal static void Init()
		{
			Resolve();
		}

		internal static bool Register(string displayName, Action openPanel)
		{
			if (string.IsNullOrEmpty(displayName) || openPanel == null)
			{
				return false;
			}
			Component val = Resolve();
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			if (cachedRegister == null)
			{
				Logger.LogError("The QuickConfig launcher on this machine has no compatible Register method; '" + displayName + "' will not appear in it.");
				return false;
			}
			try
			{
				cachedRegister.Invoke(val, new object[2] { displayName, openPanel });
				return true;
			}
			catch (Exception ex)
			{
				Logger.LogError("Could not register '" + displayName + "' with the QuickConfig launcher: " + ex.Message);
				return false;
			}
		}

		internal static void Unregister(string displayName)
		{
			if (string.IsNullOrEmpty(displayName))
			{
				return;
			}
			Component val = Resolve();
			if ((Object)(object)val == (Object)null || cachedUnregister == null)
			{
				return;
			}
			try
			{
				cachedUnregister.Invoke(val, new object[1] { displayName });
			}
			catch (Exception ex)
			{
				Logger.LogWarning("Could not unregister '" + displayName + "' from the QuickConfig launcher: " + ex.Message);
			}
		}

		private static Component Resolve()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			if ((Object)(object)cachedBroker != (Object)null)
			{
				return cachedBroker;
			}
			cachedRegister = null;
			cachedUnregister = null;
			GameObject val = null;
			try
			{
				val = GameObject.Find("ModQuickConfigLauncher");
			}
			catch (Exception)
			{
			}
			if ((Object)(object)val == (Object)null)
			{
				try
				{
					val = new GameObject("ModQuickConfigLauncher");
					Object.DontDestroyOnLoad((Object)(object)val);
					val.AddComponent<QuickConfigBroker>();
				}
				catch (Exception ex2)
				{
					Logger.LogError("Could not create the QuickConfig launcher: " + ex2.Message);
					return null;
				}
			}
			Component val2 = null;
			Component[] components = val.GetComponents<Component>();
			foreach (Component val3 in components)
			{
				if ((Object)(object)val3 != (Object)null && ((object)val3).GetType().Name == "QuickConfigBroker")
				{
					val2 = val3;
					break;
				}
			}
			if ((Object)(object)val2 == (Object)null)
			{
				return null;
			}
			Type type = ((object)val2).GetType();
			cachedRegister = type.GetMethod("Register", BindingFlags.Instance | BindingFlags.Public, null, new Type[2]
			{
				typeof(string),
				typeof(Action)
			}, null);
			cachedUnregister = type.GetMethod("Unregister", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(string) }, null);
			if (!loggedOwner)
			{
				loggedOwner = true;
				int num = 1;
				try
				{
					PropertyInfo property = type.GetProperty("BrokerVersion", BindingFlags.Instance | BindingFlags.Public);
					if (property != null)
					{
						num = (int)property.GetValue(val2, null);
					}
				}
				catch (Exception)
				{
				}
				Logger.LogInfo($"QuickConfig launcher v{num} owned by " + $"{type.Assembly.GetName().Name}; this mod carries v{2}.");
				if (num < 2)
				{
					Logger.LogInfo("That copy is older than this one. Registration still works; the launcher UI is whatever the owning mod shipped.");
				}
			}
			cachedBroker = val2;
			return cachedBroker;
		}
	}
	internal static class ConfigUIPicker
	{
		private const float PanelW = 420f;

		private const float PanelH = 520f;

		private const float RowH = 30f;

		private const int MaxRows = 400;

		private static GameObject overlay;

		internal static bool IsOpen => (Object)(object)overlay != (Object)null;

		internal static void ShowPicker(string title, IList<string> options, string current, Action<string> onPick)
		{
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: 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_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: 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_0132: Expected O, but got Unknown
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Expected O, but got Unknown
			Close();
			if (GUIManager.Instance == null || (Object)(object)GUIManager.CustomGUIFront == (Object)null)
			{
				return;
			}
			List<string> all = new List<string>();
			if (options != null)
			{
				foreach (string option in options)
				{
					if (!string.IsNullOrEmpty(option))
					{
						all.Add(option);
					}
				}
			}
			all.Sort(StringComparer.OrdinalIgnoreCase);
			overlay = ConfigUI.NewUI("ConfigUIPickerOverlay", GUIManager.CustomGUIFront.transform, typeof(Image));
			RectTransform val = (RectTransform)overlay.transform;
			val.anchorMin = Vector2.zero;
			val.anchorMax = Vector2.one;
			val.offsetMin = Vector2.zero;
			val.offsetMax = Vector2.zero;
			((Graphic)overlay.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.35f);
			Button obj = overlay.AddComponent<Button>();
			((Selectable)obj).transition = (Transition)0;
			((UnityEvent)obj.onClick).AddListener(new UnityAction(Close));
			overlay.AddComponent<ConfigUI.ConfigUIInputGuard>().Hold();
			GameObject obj2 = GUIManager.Instance.CreateWoodpanel(overlay.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), 420f, 520f, true);
			ConfigUI.AddText(obj2.transform, 0f, 14f, 420f, 30f, title, 18, (TextAnchor)4, GUIManager.Instance.ValheimYellow);
			InputField val2 = ConfigUI.AddTextField(obj2.transform, 16f, 52f, 320f, "", null, (ContentType)0, ConfigUI.L("$menu_filter", "Filter") + "...");
			ConfigUI.AddButton(obj2.transform, 344f, 52f, 60f, ConfigUI.L("$menu_close", "Close"), new UnityAction(Close), 28f);
			ConfigUI.CreateScroll(obj2.transform, 16f, 92f, 388f, 404f, out var content, out var contentW);
			if ((Object)(object)content == (Object)null)
			{
				return;
			}
			Action<string> rebuild = null;
			rebuild = delegate(string needle)
			{
				//IL_0014: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
				//IL_00dd: Expected O, but got Unknown
				foreach (Transform item in content)
				{
					Object.Destroy((Object)(object)((Component)item).gameObject);
				}
				int num = 0;
				foreach (string item2 in all)
				{
					if (string.IsNullOrEmpty(needle) || item2.IndexOf(needle, StringComparison.OrdinalIgnoreCase) >= 0)
					{
						if (num >= 400)
						{
							break;
						}
						num++;
						string picked = item2;
						ConfigUI.AddButton(ConfigUI.NewLayoutRow(content, contentW, 30f).transform, 0f, 0f, contentW, picked, (UnityAction)delegate
						{
							Close();
							onPick?.Invoke(picked);
						}, 28f);
					}
				}
				if (num == 0)
				{
					ConfigUI.AddText(ConfigUI.NewLayoutRow(content, contentW, 30f).transform, 4f, 0f, contentW, 30f, ConfigUI.L("$modquickconfig_no_matches", "No matches"), 14, (TextAnchor)3);
				}
				else if (num >= 400)
				{
					GameObject obj3 = ConfigUI.NewLayoutRow(content, contentW, 30f);
					ConfigUI.AddText(text: ConfigUI.L("$modquickconfig_more_matches", "... $1 more, type to narrow").Replace("$1", (all.Count - num).ToString()), parent: obj3.transform, x: 4f, y: 0f, w: contentW, h: 30f, fontSize: 13, anchor: (TextAnchor)3);
				}
			};
			((UnityEvent<string>)(object)val2.onValueChanged).AddListener((UnityAction<string>)delegate(string needle)
			{
				rebuild(needle);
			});
			rebuild("");
		}

		internal static void Close()
		{
			if (!((Object)(object)overlay == (Object)null))
			{
				Object.Destroy((Object)(object)overlay);
				overlay = null;
			}
		}
	}
	internal static class ConfigUIPrompt
	{
		private const float PanelW = 460f;

		private static GameObject overlay;

		internal static void Show(string title, string label, string initial, string warning, Action<string> onAccept)
		{
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: 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_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Expected O, but got Unknown
			//IL_026e: Unknown result type (might be due to invalid IL or missing references)
			//IL_027d: Expected O, but got Unknown
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			Close();
			if (GUIManager.Instance != null && !((Object)(object)GUIManager.CustomGUIFront == (Object)null))
			{
				bool flag = !string.IsNullOrEmpty(warning);
				float num = (flag ? 96f : 0f);
				float num2 = 190f + num;
				overlay = ConfigUI.NewUI("ConfigUIPromptOverlay", GUIManager.CustomGUIFront.transform, typeof(Image));
				RectTransform val = (RectTransform)overlay.transform;
				val.anchorMin = Vector2.zero;
				val.anchorMax = Vector2.one;
				val.offsetMin = Vector2.zero;
				val.offsetMax = Vector2.zero;
				((Graphic)overlay.GetComponent<Image>()).color = new Color(0f, 0f, 0f, 0.45f);
				overlay.AddComponent<ConfigUI.ConfigUIInputGuard>().Hold();
				GameObject val2 = GUIManager.Instance.CreateWoodpanel(overlay.transform, new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), new Vector2(0f, 0f), 460f, num2, true);
				ConfigUI.AddText(val2.transform, 0f, 14f, 460f, 30f, title, 18, (TextAnchor)4, GUIManager.Instance.ValheimYellow);
				float num3 = 56f;
				if (flag)
				{
					ConfigUI.AddText(val2.transform, 20f, num3, 420f, num - 8f, warning, 13, (TextAnchor)0, (Color?)new Color(0.98f, 0.75f, 0.14f));
					num3 += num;
				}
				ConfigUI.AddText(val2.transform, 20f, num3, 120f, 28f, label, 15, (TextAnchor)3);
				InputField field = ConfigUI.AddTextField(val2.transform, 140f, num3, 300f, initial, null, (ContentType)0, null, 64);
				num3 += 46f;
				ConfigUI.AddButton(val2.transform, 20f, num3, 190f, ConfigUI.L("$menu_cancel", "Cancel"), new UnityAction(Close), 34f);
				ConfigUI.AddButton(val2.transform, 250f, num3, 190f, ConfigUI.L("$menu_ok", "OK"), (UnityAction)delegate
				{
					string text = field.text;
					Close();
					onAccept?.Invoke(text);
				}, 34f);
				((Selectable)field).Select();
				field.ActivateInputField();
			}
		}

		internal static void Close()
		{
			if (!((Object)(object)overlay == (Object)null))
			{
				Object.Destroy((Object)(object)overlay);
				overlay = null;
			}
		}
	}
	internal static class ConfigUIStartupPopups
	{
		internal const int OrderWelcome = 100;

		internal const int OrderNotice = 200;

		private static Component cachedQueue;

		private static MethodInfo cachedEnqueue;

		private static MethodInfo cachedCancel;

		private static bool loggedOwner;

		internal static bool Enqueue(string key, int order, Func<bool> tryOpen, Func<bool> isOpen)
		{
			if (string.IsNullOrEmpty(key) || tryOpen == null || isOpen == null)
			{
				return false;
			}
			if (GUIManager.IsHeadless())
			{
				return false;
			}
			Component val = Resolve();
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			if (cachedEnqueue == null)
			{
				Logger.LogError("The startup popup queue on this machine has no compatible Enqueue method; '" + key + "' will not be shown.");
				return false;
			}
			try
			{
				return (bool)cachedEnqueue.Invoke(val, new object[4] { key, order, tryOpen, isOpen });
			}
			catch (Exception ex)
			{
				Logger.LogError("Could not queue the startup popup '" + key + "': " + ex.Message);
				return false;
			}
		}

		internal static void Cancel(string key)
		{
			if (string.IsNullOrEmpty(key) || GUIManager.IsHeadless())
			{
				return;
			}
			Component val = Resolve();
			if ((Object)(object)val == (Object)null || cachedCancel == null)
			{
				return;
			}
			try
			{
				cachedCancel.Invoke(val, new object[1] { key });
			}
			catch (Exception ex)
			{
				Logger.LogWarning("Could not cancel the startup popup '" + key + "': " + ex.Message);
			}
		}

		private static Component Resolve()
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Expected O, but got Unknown
			if ((Object)(object)cachedQueue != (Object)null)
			{
				return cachedQueue;
			}
			cachedEnqueue = null;
			cachedCancel = null;
			GameObject val = null;
			try
			{
				val = GameObject.Find("ModStartupPopupQueue");
			}
			catch (Exception)
			{
			}
			if ((Object)(object)val == (Object)null)
			{
				try
				{
					val = new GameObject("ModStartupPopupQueue");
					Object.DontDestroyOnLoad((Object)(object)val);
					val.AddComponent<StartupPopupQueue>();
				}
				catch (Exception ex2)
				{
					Logger.LogError("Could not create the startup popup queue: " + ex2.Message);
					return null;
				}
			}
			Component val2 = null;
			Component[] components = val.GetComponents<Component>();
			foreach (Component val3 in components)
			{
				if ((Object)(object)val3 != (Object)null && ((object)val3).GetType().Name == "StartupPopupQueue")
				{
					val2 = val3;
					break;
				}
			}
			if ((Object)(object)val2 == (Object)null)
			{
				try
				{
					val2 = (Component)(object)val.AddComponent<StartupPopupQueue>();
				}
				catch (Exception ex3)
				{
					Logger.LogError("Could not create the startup popup queue: " + ex3.Message);
					return null;
				}
			}
			Type type = ((object)val2).GetType();
			cachedEnqueue = type.GetMethod("Enqueue", BindingFlags.Instance | BindingFlags.Public, null, new Type[4]
			{
				typeof(string),
				typeof(int),
				typeof(Func<bool>),
				typeof(Func<bool>)
			}, null);
			cachedCancel = type.GetMethod("Cancel", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(string) }, null);
			if (!loggedOwner)
			{
				loggedOwner = true;
				int num = 0;
				try
				{
					PropertyInfo property = type.GetProperty("QueueVersion", BindingFlags.Instance | BindingFlags.Public);
					if (property != null)
					{
						num = (int)property.GetValue(val2, null);
					}
				}
				catch (Exception)
				{
				}
				Logger.LogInfo($"Startup popup queue v{num} owned by " + $"{type.Assembly.GetName().Name}; this mod carries v{1}.");
			}
			cachedQueue = val2;
			return cachedQueue;
		}
	}
	internal class QuickConfigBroker : MonoBehaviour
	{
		internal const string BrokerObjectName = "ModQuickConfigLauncher";

		internal const string BrokerTypeName = "QuickConfigBroker";

		internal const string ButtonObjectName = "ModQuickConfigButton";

		internal const int ContractVersion = 2;

		private const float ButtonW = 150f;

		private const float ButtonH = 38f;

		private const float PanelW = 320f;

		private static QuickConfigBroker Instance;

		private static Harmony harmony;

		private readonly Dictionary<string, Action> entries = new Dictionary<string, Action>(StringComparer.Ordinal);

		private readonly List<string> order = new List<string>();

		private GameObject mainMenuButton;

		private GameObject pauseButton;

		private GameObject listPanel;

		public int BrokerVersion => 2;

		public void Register(string modName, Action openPanel)
		{
			if (!string.IsNullOrEmpty(modName) && openPanel != null)
			{
				if (!entries.ContainsKey(modName))
				{
					order.Add(modName);
				}
				entries[modName] = openPanel;
				RefreshVisibility();
			}
		}

		public void Unregister(string modName)
		{
			if (!string.IsNullOrEmpty(modName))
			{
				if (entries.Remove(modName))
				{
					order.Remove(modName);
				}
				if ((Object)(object)listPanel != (Object)null)
				{
					CloseList();
				}
				RefreshVisibility();
			}
		}

		public bool IsRegistered(string modName)
		{