Decompiled source of Auto Map Pins v1.0.1

DigiMapPins.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using AutoMapPins;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using DigiCore;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.6.2", FrameworkDisplayName = ".NET Framework 4.6.2")]
[assembly: AssemblyCompany("DigiMapPins")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("DigiMapPins")]
[assembly: AssemblyTitle("DigiMapPins")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
internal static class SettingOrder
{
	internal sealed class ConfigurationManagerAttributes
	{
		public int? Order;
	}

	internal static void Apply(ConfigFile config)
	{
		//IL_0122: Unknown result type (might be due to invalid IL or missing references)
		//IL_012c: Expected O, but got Unknown
		FieldInfo fieldInfo = AccessTools.Field(typeof(ConfigEntryBase), "<Description>k__BackingField");
		if (fieldInfo == null)
		{
			return;
		}
		int num = 1000;
		foreach (ConfigDefinition item in config.Keys.ToList())
		{
			ConfigEntryBase val = config[item];
			ConfigDescription description = val.Description;
			object[] array = ((description != null) ? description.Tags : null) ?? new object[0];
			object obj = array.FirstOrDefault((object t) => t != null && t.GetType().Name == "ConfigurationManagerAttributes");
			if (obj != null)
			{
				FieldInfo fieldInfo2 = AccessTools.Field(obj.GetType(), "Order");
				if (fieldInfo2 != null && fieldInfo2.GetValue(obj) == null)
				{
					fieldInfo2.SetValue(obj, num);
				}
			}
			else
			{
				fieldInfo.SetValue(val, (object?)new ConfigDescription(((description != null) ? description.Description : null) ?? "", (description != null) ? description.AcceptableValues : null, array.Concat(new object[1]
				{
					new ConfigurationManagerAttributes
					{
						Order = num
					}
				}).ToArray()));
			}
			num--;
		}
	}
}
internal static class StoreRules
{
	private static bool _resolved;

	private static MethodInfo _readMarker;

	private static PropertyInfo _settings;

	private static PropertyInfo _useMarkers;

	private static PropertyInfo _canDeposit;

	private static PropertyInfo _canWithdraw;

	private static MethodInfo _isProtected;

	private static void Resolve()
	{
		if (_resolved)
		{
			return;
		}
		_resolved = true;
		try
		{
			Type type = AccessTools.TypeByName("LocalCraftFromStoragePrime.ContainerPolicyApi");
			Type type2 = AccessTools.TypeByName("LocalCraftFromStoragePrime.ContainerMarkerPolicy");
			Type type3 = AccessTools.TypeByName("LocalCraftFromStoragePrime.Plugin");
			if (!(type == null) && !(type2 == null) && !(type3 == null))
			{
				_readMarker = AccessTools.Method(type, "ReadMarker", new Type[2]
				{
					typeof(Inventory),
					typeof(bool)
				}, (Type[])null);
				_settings = AccessTools.Property(type3, "Settings");
				_useMarkers = ((_settings != null) ? AccessTools.Property(_settings.PropertyType, "UseContainerMarkers") : null);
				_canDeposit = AccessTools.Property(type2, "CanDeposit");
				_canWithdraw = AccessTools.Property(type2, "CanWithdraw");
				_isProtected = AccessTools.Method(type2, "IsProtectedPosition", new Type[2]
				{
					typeof(int),
					typeof(int)
				}, (Type[])null);
			}
		}
		catch (Exception)
		{
			_readMarker = null;
		}
	}

	private static object Marker(Inventory inv)
	{
		Resolve();
		if (_readMarker == null || _canDeposit == null || _canWithdraw == null || _isProtected == null)
		{
			return null;
		}
		try
		{
			bool flag = true;
			if (_settings != null && _useMarkers != null)
			{
				flag = (bool)_useMarkers.GetValue(_settings.GetValue(null));
			}
			return _readMarker.Invoke(null, new object[2] { inv, flag });
		}
		catch (Exception)
		{
			return null;
		}
	}

	internal static bool CanDeposit(Inventory inv)
	{
		object obj = Marker(inv);
		if (obj != null)
		{
			return (bool)_canDeposit.GetValue(obj);
		}
		return true;
	}

	internal static bool CanWithdraw(Inventory inv)
	{
		object obj = Marker(inv);
		if (obj != null)
		{
			return (bool)_canWithdraw.GetValue(obj);
		}
		return true;
	}

	internal static bool IsProtected(Inventory inv, ItemData item)
	{
		return IsProtectedSlot(inv, item.m_gridPos.x, item.m_gridPos.y);
	}

	internal static bool IsProtectedSlot(Inventory inv, int x, int y)
	{
		object obj = Marker(inv);
		if (obj != null)
		{
			return (bool)_isProtected.Invoke(obj, new object[2] { x, y });
		}
		return false;
	}

	internal static Func<int, int, bool> ProtectedSlots(Inventory inv)
	{
		object m = Marker(inv);
		if (m == null)
		{
			return null;
		}
		return (int x, int y) => (bool)_isProtected.Invoke(m, new object[2] { x, y });
	}

	internal static Container PickOutputChest(List<Container> nearestFirst, GameObject prefab, int amount)
	{
		string shared = prefab.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_name;
		List<Container> source = nearestFirst.Where((Container c) => CanDeposit(c.GetInventory()) && c.GetInventory().CanAddItem(prefab, amount)).ToList();
		return ((IEnumerable<Container>)source).FirstOrDefault((Func<Container, bool>)((Container c) => c.GetInventory().GetAllItems().Any((ItemData i) => i?.m_shared != null && i.m_shared.m_name == shared && !IsProtected(c.GetInventory(), i)))) ?? source.FirstOrDefault();
	}

	internal static bool TakeOne(List<Container> nearestFirst, Func<ItemData, bool> match, out ItemData taken)
	{
		foreach (Container item in nearestFirst)
		{
			Inventory inv = item.GetInventory();
			if (CanWithdraw(inv))
			{
				ItemData val = ((IEnumerable<ItemData>)inv.GetAllItems()).FirstOrDefault((Func<ItemData, bool>)((ItemData i) => match(i) && !IsProtected(inv, i)));
				if (val != null)
				{
					taken = val.Clone();
					inv.RemoveOneItem(val);
					return true;
				}
			}
		}
		taken = null;
		return false;
	}
}
namespace DigiCore
{
	public static class ChestFlags
	{
		public const string NoStore = "digi_nostore";

		public static bool StoreBlocked(Container chest)
		{
			if ((Object)(object)chest == (Object)null)
			{
				return false;
			}
			ZNetView component = ((Component)chest).GetComponent<ZNetView>();
			if ((Object)(object)component != (Object)null && component.IsValid())
			{
				return component.GetZDO().GetBool("digi_nostore", false);
			}
			return false;
		}
	}
	public sealed class ModuleInfo
	{
		public readonly Type Type;

		public readonly string Title;

		public readonly string OldGuid;

		public readonly string Description;

		public readonly string[] Requires;

		public readonly bool DefaultOn;

		public ModuleInfo(Type type, string title, string oldGuid, string description, string[] requires = null, bool defaultOn = true)
		{
			Type = type;
			Title = title;
			OldGuid = oldGuid;
			Description = description;
			Requires = requires ?? new string[0];
			DefaultOn = defaultOn;
		}
	}
	public abstract class DigiPlugin : BaseUnityPlugin
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static Func<string, string> <>9__11_0;

			public static Func<string, bool> <>9__11_1;

			public static Func<string, bool> <>9__11_2;

			public static Func<string, string> <>9__11_3;

			public static Func<string, string[]> <>9__19_0;

			public static Func<string[], string> <>9__19_1;

			public static Func<string[], string> <>9__19_4;

			public static Func<IGrouping<string, string[]>, string> <>9__19_2;

			public static PopupButtonCallback <>9__19_3;

			public static Func<string, bool> <>9__23_0;

			internal string <Awake>b__11_0(string l)
			{
				return l.Trim();
			}

			internal bool <Awake>b__11_1(string l)
			{
				return l.Length > 0;
			}

			internal bool <Awake>b__11_2(string r)
			{
				return !Chainloader.PluginInfos.ContainsKey(r);
			}

			internal string <Awake>b__11_3(string r)
			{
				if (!RequirementNames.TryGetValue(r, out var value))
				{
					return r;
				}
				return value;
			}

			internal string[] <ShowDuplicates>b__19_0(string d)
			{
				return d.Split(new char[1] { '|' });
			}

			internal string <ShowDuplicates>b__19_1(string[] d)
			{
				return d[0];
			}

			internal string <ShowDuplicates>b__19_2(IGrouping<string, string[]> g)
			{
				return "<b>" + g.Key + ":</b> " + string.Join(", ", g.Select((string[] d) => d[1]));
			}

			internal string <ShowDuplicates>b__19_4(string[] d)
			{
				return d[1];
			}

			internal void <ShowDuplicates>b__19_3()
			{
				UnifiedPopup.Pop();
			}

			internal bool <Apply>b__23_0(string r)
			{
				return !Chainloader.PluginInfos.ContainsKey(r);
			}
		}

		public const string ModulesSection = "0 - Sub-mods";

		internal static DigiPlugin StartingHost;

		internal static ModuleInfo StartingModule;

		private static readonly Dictionary<string, string> RequirementNames = new Dictionary<string, string>
		{
			{ "randyknapp.mods.epicloot", "Epic Loot" },
			{ "com.jotunn.jotunn", "Jotunn" },
			{ "ValheimLegends", "Valheim Legends" },
			{ "vapok.mods.adventurebackpacks", "Adventure Backpacks" },
			{ "MidnightsFX.StarLevelSystem", "Star Level System" },
			{ "sosal.nordicrugs", "Nordic Rugs" },
			{ "LuminairPrime.valheim.localcraftfromstorageprime", "Local Craft From Storage Prime" }
		};

		private readonly Dictionary<ModuleInfo, DigiModule> _running = new Dictionary<ModuleInfo, DigiModule>();

		private readonly Dictionary<ModuleInfo, ConfigEntry<bool>> _switches = new Dictionary<ModuleInfo, ConfigEntry<bool>>();

		private HashSet<string> _migrated;

		private const string DuplicatesKey = "digi.valheim.duplicates";

		private const string DuplicatesShownKey = "digi.valheim.duplicates.shown";

		protected abstract ModuleInfo[] Modules { get; }

		private string MigratedFile => Path.Combine(Paths.ConfigPath, ((BaseUnityPlugin)this).Info.Metadata.GUID + ".migrated.txt");

		private static List<string> Duplicates
		{
			get
			{
				List<string> list = AppDomain.CurrentDomain.GetData("digi.valheim.duplicates") as List<string>;
				if (list == null)
				{
					list = new List<string>();
					AppDomain.CurrentDomain.SetData("digi.valheim.duplicates", list);
				}
				return list;
			}
		}

		protected virtual void Awake()
		{
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = true;
			((BaseUnityPlugin)this).Config.Save();
			_migrated = (File.Exists(MigratedFile) ? new HashSet<string>(from l in File.ReadAllLines(MigratedFile)
				select l.Trim() into l
				where l.Length > 0
				select l) : new HashSet<string>());
			bool flag = !_migrated.Contains("#switches");
			ModuleInfo[] modules = Modules;
			foreach (ModuleInfo moduleInfo in modules)
			{
				List<string> list = moduleInfo.Requires.Where((string r) => !Chainloader.PluginInfos.ContainsKey(r)).ToList();
				string value;
				string text = ((moduleInfo.Requires.Length == 0) ? "" : (" Needs " + string.Join(" and ", moduleInfo.Requires.Select((string r) => (!RequirementNames.TryGetValue(r, out value)) ? r : value)) + "."));
				ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>("0 - Sub-mods", moduleInfo.Title, moduleInfo.DefaultOn, moduleInfo.Description + text);
				if (flag && !moduleInfo.DefaultOn && File.Exists(OldConfigPath(moduleInfo)))
				{
					val.Value = true;
				}
				_switches[moduleInfo] = val;
				ModuleInfo captured = moduleInfo;
				val.SettingChanged += delegate
				{
					Apply(captured);
				};
				if (list.Count > 0)
				{
					((BaseUnityPlugin)this).Logger.LogInfo((object)(moduleInfo.Title + ": off, needs " + string.Join(", ", list) + "."));
				}
			}
			if (flag)
			{
				Remember("#switches");
			}
			modules = Modules;
			foreach (ModuleInfo module in modules)
			{
				Apply(module);
			}
		}

		private void Start()
		{
			foreach (KeyValuePair<ModuleInfo, DigiModule> item in _running.ToList())
			{
				if (!((Object)(object)item.Value == (Object)null) && Chainloader.PluginInfos.ContainsKey(item.Key.OldGuid))
				{
					item.Value.Teardown();
					_running.Remove(item.Key);
					Forget(item.Key.OldGuid);
					ReportDuplicate(item.Key);
				}
			}
			SettingOrder.Apply(((BaseUnityPlugin)this).Config);
			if (!Application.isBatchMode)
			{
				((MonoBehaviour)this).StartCoroutine(ShowDuplicates());
			}
		}

		private void ReportDuplicate(ModuleInfo module)
		{
			((BaseUnityPlugin)this).Logger.LogWarning((object)(module.Title + ": not started, because the separate mod (" + module.OldGuid + ") is installed too. Remove that one."));
			string item = ((BaseUnityPlugin)this).Info.Metadata.Name.Replace("Digi's ", "") + "|" + module.Title;
			if (!Duplicates.Contains(item))
			{
				Duplicates.Add(item);
			}
		}

		internal void ReportReplaced(string what)
		{
			string item = ((BaseUnityPlugin)this).Info.Metadata.Name.Replace("Digi's ", "") + "|" + what;
			if (!Duplicates.Contains(item))
			{
				Duplicates.Add(item);
			}
		}

		private IEnumerator ShowDuplicates()
		{
			while ((Object)(object)FejdStartup.instance == (Object)null || !UnifiedPopup.IsAvailable())
			{
				yield return (object)new WaitForSeconds(0.5f);
			}
			yield return (object)new WaitForSeconds(1f);
			if (Duplicates.Count == 0 || AppDomain.CurrentDomain.GetData("digi.valheim.duplicates.shown") != null)
			{
				yield break;
			}
			AppDomain.CurrentDomain.SetData("digi.valheim.duplicates.shown", true);
			IEnumerable<string> values = from d in Duplicates
				select d.Split(new char[1] { '|' }) into d
				group d by d[0] into g
				select "<b>" + g.Key + ":</b> " + string.Join(", ", g.Select((string[] d) => d[1]));
			string text = "These mods are installed twice: on their own and inside one of our combined mods.\n\n" + string.Join("\n", values) + "\n\nThe copy in the combined mod stays off until you remove the separate ones in your mod manager (or make a new profile with Digi Modpack). Your settings are copied over.";
			object obj = <>c.<>9__19_3;
			if (obj == null)
			{
				PopupButtonCallback val = delegate
				{
					UnifiedPopup.Pop();
				};
				<>c.<>9__19_3 = val;
				obj = (object)val;
			}
			UnifiedPopup.Push((PopupBase)new WarningPopup("Mods installed twice", text, (PopupButtonCallback)obj, false));
		}

		private static string OldConfigPath(ModuleInfo module)
		{
			return Path.Combine(Paths.ConfigPath, module.OldGuid + ".cfg");
		}

		private void Remember(string key)
		{
			if (!_migrated.Add(key))
			{
				return;
			}
			try
			{
				File.AppendAllText(MigratedFile, key + Environment.NewLine);
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not write " + MigratedFile + ": " + ex.Message));
			}
		}

		private void Forget(string key)
		{
			if (!_migrated.Remove(key))
			{
				return;
			}
			try
			{
				File.WriteAllLines(MigratedFile, _migrated.ToArray());
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("Could not write " + MigratedFile + ": " + ex.Message));
			}
		}

		private void Apply(ModuleInfo module)
		{
			bool value = _switches[module].Value;
			_running.TryGetValue(module, out var value2);
			if (value && (Object)(object)value2 == (Object)null)
			{
				if (!module.Requires.Any((string r) => !Chainloader.PluginInfos.ContainsKey(r)))
				{
					if (Chainloader.PluginInfos.ContainsKey(module.OldGuid))
					{
						ReportDuplicate(module);
					}
					else
					{
						StartModule(module);
					}
				}
			}
			else if (!value && (Object)(object)value2 != (Object)null)
			{
				value2.Teardown();
				_running.Remove(module);
				((BaseUnityPlugin)this).Logger.LogInfo((object)(module.Title + ": switched off."));
			}
		}

		private void StartModule(ModuleInfo module)
		{
			StartingHost = this;
			StartingModule = module;
			try
			{
				DigiModule digiModule = (DigiModule)(object)((Component)this).gameObject.AddComponent(module.Type);
				digiModule.Host = this;
				digiModule.Info2 = module;
				_running[module] = digiModule;
				MigrateOldSettings(module, digiModule);
			}
			catch (Exception arg)
			{
				((BaseUnityPlugin)this).Logger.LogError((object)$"{module.Title} could not start: {arg}");
			}
			finally
			{
				StartingHost = null;
				StartingModule = null;
			}
			SettingOrder.Apply(((BaseUnityPlugin)this).Config);
		}

		private void MigrateOldSettings(ModuleInfo module, DigiModule component)
		{
			if (_migrated.Contains(module.OldGuid))
			{
				return;
			}
			string path = OldConfigPath(module);
			if (File.Exists(path) && component.ConfigOrNull != null)
			{
				Dictionary<string, string> dictionary = ReadCfg(path);
				int num = 0;
				foreach (ModuleConfig.Bound entry in component.ConfigOrNull.Entries)
				{
					if (dictionary.TryGetValue(entry.Section + "\n" + entry.Key, out var value))
					{
						try
						{
							entry.Entry.SetSerializedValue(value);
							num++;
						}
						catch (Exception ex)
						{
							((BaseUnityPlugin)this).Logger.LogWarning((object)(module.Title + ": could not copy '" + entry.Key + "': " + ex.Message));
						}
					}
				}
				((BaseUnityPlugin)this).Logger.LogInfo((object)$"{module.Title}: copied {num} setting(s) from {Path.GetFileName(path)}.");
			}
			Remember(module.OldGuid);
		}

		private static Dictionary<string, string> ReadCfg(string path)
		{
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			string text = "";
			string[] array = File.ReadAllLines(path);
			for (int i = 0; i < array.Length; i++)
			{
				string text2 = array[i].Trim();
				if (text2.Length == 0 || text2.StartsWith("#"))
				{
					continue;
				}
				if (text2.StartsWith("[") && text2.EndsWith("]"))
				{
					text = text2.Substring(1, text2.Length - 2);
					continue;
				}
				int num = text2.IndexOf(" = ", StringComparison.Ordinal);
				if (num > 0)
				{
					dictionary[text + "\n" + text2.Substring(0, num).Trim()] = text2.Substring(num + 3);
				}
			}
			return dictionary;
		}

		protected virtual void OnDestroy()
		{
			foreach (DigiModule item in _running.Values.ToList())
			{
				item?.Teardown();
			}
			_running.Clear();
		}

		public bool IsRunning(Type moduleType)
		{
			return _running.Any((KeyValuePair<ModuleInfo, DigiModule> p) => p.Key.Type == moduleType && (Object)(object)p.Value != (Object)null);
		}
	}
	public abstract class DigiModule : MonoBehaviour
	{
		internal DigiPlugin Host;

		internal ModuleInfo Info2;

		private ModuleConfig _config;

		private ManualLogSource _logger;

		private Harmony _harmony;

		internal ModuleConfig ConfigOrNull => _config;

		protected ModuleConfig Config => _config ?? (_config = new ModuleConfig(((BaseUnityPlugin)(Host ?? DigiPlugin.StartingHost)).Config, (Info2 ?? DigiPlugin.StartingModule).Title));

		protected ManualLogSource Logger => _logger ?? (_logger = Logger.CreateLogSource("Digi's " + (Info2 ?? DigiPlugin.StartingModule)?.Title));

		protected Harmony ModuleHarmony
		{
			get
			{
				//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)
				//IL_0045: Expected O, but got Unknown
				//IL_004a: Expected O, but got Unknown
				Harmony obj = _harmony;
				if (obj == null)
				{
					Harmony val = new Harmony(((object)this).GetType().Namespace?.ToLowerInvariant() + "." + Guid.NewGuid().ToString("N"));
					Harmony val2 = val;
					_harmony = val;
					obj = val2;
				}
				return obj;
			}
		}

		protected void ReportReplacedMod(string what)
		{
			(Host ?? DigiPlugin.StartingHost)?.ReportReplaced(what);
		}

		protected Harmony PatchModule(Type type)
		{
			ModuleHarmony.PatchAll(type);
			return ModuleHarmony;
		}

		protected Harmony PatchModuleNamespace()
		{
			string text = ((object)this).GetType().Namespace;
			Type[] typesFromAssembly = AccessTools.GetTypesFromAssembly(((object)this).GetType().Assembly);
			foreach (Type type in typesFromAssembly)
			{
				if (type.Namespace == text || (type.Namespace != null && text != null && type.Namespace.StartsWith(text + ".")))
				{
					ModuleHarmony.CreateClassProcessor(type).Patch();
				}
			}
			return ModuleHarmony;
		}

		internal void Teardown()
		{
			try
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			catch (Exception ex)
			{
				Logger.LogWarning((object)("Unpatch: " + ex.Message));
			}
			Object.Destroy((Object)(object)this);
		}
	}
	public sealed class ModuleConfig
	{
		public sealed class Bound
		{
			public string Section;

			public string Key;

			public ConfigEntryBase Entry;
		}

		private readonly ConfigFile _file;

		private readonly string _prefix;

		internal readonly List<Bound> Entries = new List<Bound>();

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

		public ConfigFile File => _file;

		public string ConfigFilePath => _file.ConfigFilePath;

		internal ModuleConfig(ConfigFile file, string title)
		{
			_file = file;
			_prefix = title + " - ";
		}

		public void Reload()
		{
		}

		public void Save()
		{
			_file.Save();
		}

		public ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, ConfigDescription configDescription = null)
		{
			section = Clean(section);
			key = Clean(key);
			ConfigEntry<T> val = _file.Bind<T>(_prefix + section, key, defaultValue, configDescription);
			if (!Entries.Any((Bound b) => b.Section == section && b.Key == key))
			{
				Entries.Add(new Bound
				{
					Section = section,
					Key = key,
					Entry = (ConfigEntryBase)(object)val
				});
			}
			return val;
		}

		private static string Clean(string name)
		{
			if (name.IndexOfAny(Invalid) < 0)
			{
				return name;
			}
			string[] value = name.Split(Invalid, StringSplitOptions.None);
			return string.Join("", value).Trim();
		}

		public ConfigEntry<T> Bind<T>(string section, string key, T defaultValue, string description)
		{
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Expected O, but got Unknown
			return Bind(section, key, defaultValue, new ConfigDescription(description, (AcceptableValueBase)null, Array.Empty<object>()));
		}

		public ConfigEntry<T> Bind<T>(ConfigDefinition definition, T defaultValue, ConfigDescription configDescription = null)
		{
			return Bind(definition.Section, definition.Key, defaultValue, configDescription);
		}

		public bool TryGetEntry<T>(ConfigDefinition definition, out ConfigEntry<T> entry)
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Expected O, but got Unknown
			return _file.TryGetEntry<T>(new ConfigDefinition(_prefix + definition.Section, definition.Key), ref entry);
		}
	}
}
namespace DigiMapPins
{
	[BepInPlugin("digi.valheim.automappins", "Digi's Auto Map Pins", "1.0.1")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	public class Plugin : DigiPlugin
	{
		public const string Guid = "digi.valheim.automappins";

		public const string Name = "Digi's Auto Map Pins";

		public const string Version = "1.0.1";

		protected override ModuleInfo[] Modules { get; } = new ModuleInfo[1]
		{
			new ModuleInfo(typeof(AutoMapPins.Plugin), "Auto Map Pins", "com.jekkle.valheim.carturmappins", "Pins ore, plants, dungeons, chests, spawners and portals on your map as you come near, with a switch and icon per thing per biome.")
		};
	}
}
namespace AutoMapPins
{
	internal static class CarturImport
	{
		private const int Version = 5;

		internal static void Run()
		{
			//IL_0133: Unknown result type (might be due to invalid IL or missing references)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_0219: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: 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_01c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_029f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02b6: Unknown result type (might be due to invalid IL or missing references)
			PlayerProfile val = (((Object)(object)Game.instance != (Object)null) ? Game.instance.GetPlayerProfile() : null);
			if (val == null || (Object)(object)ZNet.instance == (Object)null || (Object)(object)Minimap.instance == (Object)null || Records.Key == null)
			{
				return;
			}
			string path = Path.Combine(Records.Folder, Records.Key + ".cartur");
			if (File.Exists(path) && int.TryParse(File.ReadAllText(path).Trim(), out var result) && result >= 5)
			{
				return;
			}
			string text = Find(ZNet.instance.GetWorldUID(), val.GetFilename());
			if (text == null)
			{
				return;
			}
			List<PinData> list = MapPins.GamePins();
			if (list == null)
			{
				return;
			}
			int num = 0;
			int num2 = 0;
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			string[] array = File.ReadAllLines(text);
			foreach (string obj in array)
			{
				string[] array2 = obj.Split(new char[1] { '|' });
				if (array2.Length < 6 || !float.TryParse(array2[1], NumberStyles.Float, invariantCulture, out var result2) || !float.TryParse(array2[2], NumberStyles.Float, invariantCulture, out var result3) || !float.TryParse(array2[3], NumberStyles.Float, invariantCulture, out var result4))
				{
					continue;
				}
				Vector3 pos = new Vector3(result2, result3, result4);
				string token = array2[4];
				string name = array2[5];
				PinData val2 = ((IEnumerable<PinData>)list).FirstOrDefault((Func<PinData, bool>)((PinData p) => p.m_save && Utils.DistanceXZ(p.m_pos, pos) < 1f && (p.m_name == token || p.m_name == name)));
				Thing thing = Map(array2[0], name);
				if (thing == null)
				{
					if (val2 != null && val2.m_name.StartsWith("$carturpins"))
					{
						Minimap.instance.RemovePin(val2);
						Minimap.instance.AddPin(val2.m_pos, val2.m_type, name, true, val2.m_checked, 0L, default(PlatformUserID));
					}
					num2++;
					continue;
				}
				if (val2 != null)
				{
					Minimap.instance.RemovePin(val2);
				}
				Record record = ((thing.Kind == Kind.Spawner) ? Records.ClosestSpawner(pos, thing.Spacing) : Records.Closest(pos, thing.Spacing, thing.Id));
				if (record != null)
				{
					if (record.Thing != thing.Id && thing.Id != "spawner")
					{
						record.Thing = thing.Id;
						record.Label = null;
						record.Icon = null;
						Records.Dirty = true;
					}
				}
				else
				{
					Records.Add(new Record
					{
						Thing = thing.Id,
						Biome = WorldGenerator.instance.GetBiome(pos),
						Pos = pos,
						Label = ((thing.Kind == Kind.Place) ? name : null),
						Checked = (val2?.m_checked ?? false)
					});
					num++;
				}
			}
			Records.Save();
			File.WriteAllText(path, 5.ToString(CultureInfo.InvariantCulture));
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"Took over {num} pins from Cartur's Map Pins ({Path.GetFileName(text)}); {num2} of a kind this mod does not pin stay as normal pins.");
			}
		}

		private static string Find(long worldUid, string character)
		{
			string configPath = Paths.ConfigPath;
			if (!Directory.Exists(configPath))
			{
				return null;
			}
			string mark = "-" + worldUid.ToString(CultureInfo.InvariantCulture) + ".";
			return Directory.GetFiles(configPath, "com.jekkle.valheim.carturmappins.*.pins.txt").FirstOrDefault(delegate(string path)
			{
				string fileName = Path.GetFileName(path);
				return fileName.Contains(mark) && fileName.EndsWith("." + character + ".pins.txt", StringComparison.OrdinalIgnoreCase);
			});
		}

		private static Thing Map(string category, string name)
		{
			string[] array = category.Split(new char[1] { ':' });
			string text = array[0];
			string text2 = ((array.Length > 1) ? array[1] : name);
			switch (text)
			{
			case "Chest":
				return Catalog.Get("chest");
			case "Spawner":
				return ((array.Length > 1) ? Spawning(array[1]) : null) ?? Catalog.Get("spawner");
			case "Beehive":
				return Catalog.Get("beehive");
			case "Ore":
				return Ore(text2);
			case "Pickable":
				return ByName(Kind.Plant, text2);
			case "LoreStone":
				return Catalog.Get("place:Runestone");
			case "BossAltar":
				return ByName(Kind.Place, text2 + " altar") ?? ByName(Kind.Place, text2);
			case "Dungeon":
				if (!(Norm(text2) == "crypt"))
				{
					if (!(Norm(text2) == "sunkencrypt"))
					{
						return ByName(Kind.Place, text2);
					}
					return Catalog.Get("place:SunkenCrypt");
				}
				return Catalog.Get("place:Crypt");
			case "Home":
				return null;
			default:
				return ByName(Kind.Place, text2) ?? ByName(Kind.Place, name);
			}
		}

		private static Thing Ore(string sub)
		{
			return Norm(sub) switch
			{
				"iron" => Catalog.Get("deposit:mudpile") ?? ByItem(Kind.Deposit, "IronScrap"), 
				"giantremains" => Catalog.Get("place:Mistlands_Giant"), 
				"sulfur" => ByItem(Kind.Plant, "SulfurStone") ?? ByItem(Kind.Deposit, "SulfurStone"), 
				_ => ByName(Kind.Deposit, sub) ?? ByItem(Kind.Deposit, sub), 
			};
		}

		private static Thing Spawning(string creature)
		{
			string wanted = Norm(creature);
			if (wanted.Length == 0 || Localization.instance == null)
			{
				return null;
			}
			return Catalog.ById.Values.FirstOrDefault((Thing t) => t.Kind == Kind.Spawner && t.Id != "spawner" && Norm(Localization.instance.Localize(t.Label)) == wanted);
		}

		private static Thing ByItem(Kind kind, string item)
		{
			string wanted = Norm(item);
			if (wanted.Length != 0)
			{
				return Catalog.ById.Values.FirstOrDefault((Thing t) => t.Kind == kind && Norm(t.IconItem).StartsWith(wanted));
			}
			return null;
		}

		private static Thing ByName(Kind kind, string name)
		{
			string wanted = Norm(name);
			if (wanted.Length == 0)
			{
				return null;
			}
			List<Thing> source = Catalog.ById.Values.Where((Thing t) => t.Kind == kind).ToList();
			return source.FirstOrDefault((Thing t) => Norm(t.Name) == wanted) ?? source.FirstOrDefault((Thing t) => Norm(t.Name).Contains(wanted));
		}

		private static string Norm(string text)
		{
			return new string((text ?? "").Where(char.IsLetter).Select(char.ToLowerInvariant).ToArray());
		}
	}
	internal enum Kind
	{
		Plant,
		Deposit,
		Beehive,
		Chest,
		Spawner,
		Place,
		Portal,
		Built
	}
	internal sealed class Thing
	{
		public string Id;

		public string Name;

		public string Label;

		public Kind Kind;

		public Biome Biomes;

		public Biome Learned;

		public bool DefaultOn;

		public float RespawnMinutes;

		public float Spacing;

		public string IconItem;

		public Sprite Icon;

		public bool IconTried;

		public Color AutoColor = Color.white;

		public bool ColorKnown;

		public readonly Slot[] Slots = new Slot[Catalog.Biomes.Length];
	}
	internal sealed class Slot
	{
		public ConfigEntry<bool> Toggle;

		public ConfigEntry<Color> Color;

		public ConfigEntry<string> Icon;
	}
	internal static class Catalog
	{
		private sealed class Known
		{
			public string Name;

			public string Icon;

			public string Label;

			public bool On = true;
		}

		internal static readonly Dictionary<string, Thing> ById = new Dictionary<string, Thing>();

		private static readonly Dictionary<int, Thing> ByPrefab = new Dictionary<int, Thing>();

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

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

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

		private static ModuleConfig _config;

		internal const string ChestId = "chest";

		internal const string SpawnerId = "spawner";

		internal const string PortalId = "portal";

		internal static readonly Biome[] Biomes;

		private static readonly HashSet<string> Bosses;

		private static readonly Regex Dungeon;

		private static readonly Regex Camp;

		private static readonly HashSet<string> Plain;

		private static readonly HashSet<string> Minor;

		private static readonly Dictionary<string, Biome> Homes;

		private static readonly HashSet<string> TameCreatures;

		private static readonly string[] Builds;

		private static readonly HashSet<string> Props;

		private static readonly Dictionary<string, Known> Places;

		private static readonly Regex Skip;

		private static readonly Regex Runestone;

		private const string CacheHeader = "# Digi's Auto Map Pins v4:";

		private static bool _cacheDirty;

		private static bool _building;

		private static readonly HashSet<string> Fresh;

		internal static bool Built { get; private set; }

		private static Biome AllBiomes => Biomes.Aggregate((Biome)0, (Biome a, Biome b) => (Biome)(a | b));

		private static string CachePath => Path.Combine(Records.Folder, "catalog.txt");

		internal static event Action Changed;

		internal static event Action Recolored;

		internal static bool IsBoss(Thing thing)
		{
			if (thing != null)
			{
				return Bosses.Contains(thing.Id);
			}
			return false;
		}

		internal static bool IsDungeon(Thing thing)
		{
			if (thing != null && thing.Kind == Kind.Place)
			{
				return Dungeon.IsMatch(thing.Id);
			}
			return false;
		}

		internal static bool IsLair(Thing thing)
		{
			if (!IsDungeon(thing))
			{
				if (thing != null && thing.Kind == Kind.Place)
				{
					return Camp.IsMatch(thing.Id);
				}
				return false;
			}
			return true;
		}

		internal unsafe static string BiomeName(Biome biome)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			if ((int)biome != 8)
			{
				if ((int)biome != 32)
				{
					if ((int)biome != 64)
					{
						return ((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString();
					}
					return "Deep North";
				}
				return "Ashlands";
			}
			return "Black Forest";
		}

		private static string Section(Biome biome)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			return $"{Array.IndexOf(Biomes, biome) + 3:00} - {BiomeName(biome)}";
		}

		internal static void Bind(ModuleConfig config)
		{
			_config = config;
			LoadCache();
		}

		private static void LoadCache()
		{
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Unknown result type (might be due to invalid IL or missing references)
			if (!File.Exists(CachePath))
			{
				return;
			}
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			string[] array = File.ReadAllLines(CachePath);
			if (array.Length == 0 || !array[0].StartsWith("# Digi's Auto Map Pins v4:", StringComparison.Ordinal))
			{
				return;
			}
			string[] array2 = array;
			Color autoColor = default(Color);
			foreach (string text in array2)
			{
				if (text.Length == 0 || text[0] == '#')
				{
					continue;
				}
				string[] array3 = text.Split(new char[1] { '\t' });
				if (array3.Length >= 10 && Enum.TryParse<Kind>(array3[3], out var result) && int.TryParse(array3[4], NumberStyles.Integer, invariantCulture, out var result2) && float.TryParse(array3[6], NumberStyles.Float, invariantCulture, out var result3) && float.TryParse(array3[7], NumberStyles.Float, invariantCulture, out var result4))
				{
					Thing thing = Add(array3[0], NoTags(array3[1]), array3[2], result, (Biome)result2, array3[5] == "1", result3, result4, (array3[8].Length > 0) ? array3[8] : null);
					if (ColorUtility.TryParseHtmlString("#" + array3[9], ref autoColor))
					{
						thing.AutoColor = autoColor;
						thing.ColorKnown = true;
					}
					if (array3.Length > 10 && int.TryParse(array3[10], NumberStyles.Integer, invariantCulture, out var result5))
					{
						thing.Learned = (Biome)result5;
					}
				}
			}
			BindAll();
		}

		internal static void SaveIfChanged()
		{
			if (_cacheDirty)
			{
				SaveCache();
			}
		}

		private static void SaveCache()
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Expected I4, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Expected I4, but got Unknown
			_cacheDirty = false;
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			List<string> list = new List<string> { "# Digi's Auto Map Pins v4: what can be found per biome (rebuilt at every world load): id, name, label, kind, biomes, on, respawn, spacing, icon, colour, biomes found in outside the spawn tables" };
			foreach (Thing value in ById.Values)
			{
				list.Add(string.Join("\t", value.Id, value.Name, value.Label, value.Kind.ToString(), ((int)value.Biomes).ToString(invariantCulture), value.DefaultOn ? "1" : "0", value.RespawnMinutes.ToString(invariantCulture), value.Spacing.ToString(invariantCulture), value.IconItem ?? "", ColorUtility.ToHtmlStringRGB(value.AutoColor), ((int)value.Learned).ToString(invariantCulture)));
			}
			try
			{
				Directory.CreateDirectory(Records.Folder);
				File.WriteAllLines(CachePath, list);
			}
			catch (IOException ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Could not save the catalog: " + ex.Message));
				}
			}
		}

		private static void BindAll()
		{
			//IL_0017: 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)
			Biome[] biomes = Biomes;
			foreach (Biome biome in biomes)
			{
				foreach (Thing item in ById.Values.Where((Thing t) => (t.Biomes & biome) > 0).OrderBy<Thing, string>((Thing t) => t.Name, StringComparer.OrdinalIgnoreCase))
				{
					BindThing(biome, item);
				}
			}
		}

		internal static bool TryBuild()
		{
			if (Built)
			{
				return true;
			}
			ZoneSystem instance = ZoneSystem.instance;
			ZNetScene instance2 = ZNetScene.instance;
			ObjectDB instance3 = ObjectDB.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance2 == (Object)null || (Object)(object)instance3 == (Object)null || instance3.m_items.Count == 0 || _config == null)
			{
				return false;
			}
			_building = true;
			try
			{
				Build(instance, instance2);
			}
			finally
			{
				_building = false;
			}
			foreach (Thing value in ById.Values)
			{
				Icons.Prepare(value);
			}
			BindAll();
			Fresh.Clear();
			Built = true;
			SaveCache();
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"Catalog: {ById.Count} kinds of things over {Biomes.Length} biomes.");
			}
			return true;
		}

		private static void Build(ZoneSystem zones, ZNetScene scene)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_024d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0335: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<string, Biome> dictionary = new Dictionary<string, Biome>();
			foreach (ZoneVegetation item in zones.m_vegetation)
			{
				if (item != null && !((Object)(object)item.m_prefab == (Object)null))
				{
					if (item.m_enable)
					{
						AddVegetation(item.m_prefab, item.m_biome);
					}
					else
					{
						dictionary[((Object)item.m_prefab).name] = (Biome)((dictionary.TryGetValue(((Object)item.m_prefab).name, out var value) ? ((int)value) : 0) | item.m_biome);
					}
				}
			}
			foreach (ZoneLocation location in zones.m_locations)
			{
				if (location != null && location.m_enable && !string.IsNullOrEmpty(location.m_prefabName))
				{
					AddLocation(location.m_prefabName, location.m_biome);
				}
			}
			Thing value2 = Add("chest", "Treasure chests", "$piece_chestwood", Kind.Chest, AllBiomes, on: true, 0f, 3f, "piece_chest_wood");
			Add("spawner", "Spawners", "Spawner", Kind.Spawner, (Biome)0, on: true, 0f, 6f, null);
			Dictionary<string, Biome> creatures = CreatureHomes(zones);
			string[] builds = Builds;
			foreach (string text in builds)
			{
				GameObject prefab = scene.GetPrefab(text);
				Piece val = ((prefab != null) ? prefab.GetComponent<Piece>() : null);
				if ((Object)(object)val != (Object)null)
				{
					ByPrefab[StringExtensionMethods.GetStableHashCode(text)] = Add("built:" + text, Localized(val.m_name, Pretty(text)), val.m_name, Kind.Built, (Biome)512, on: true, 0f, 8f, text);
				}
			}
			foreach (GameObject prefab2 in scene.m_prefabs)
			{
				if ((Object)(object)prefab2 == (Object)null || ByPrefab.ContainsKey(StringExtensionMethods.GetStableHashCode(((Object)prefab2).name)))
				{
					continue;
				}
				dictionary.TryGetValue(((Object)prefab2).name, out var value3);
				Pickable component = prefab2.GetComponent<Pickable>();
				if ((Object)(object)component != (Object)null)
				{
					AddPickup(prefab2, component, value3);
				}
				else if ((Object)(object)prefab2.GetComponent<Container>() != (Object)null && (Object)(object)prefab2.GetComponent<TombStone>() == (Object)null && ((Object)prefab2).name.IndexOf("Chest", StringComparison.OrdinalIgnoreCase) >= 0 && !((Object)prefab2).name.StartsWith("piece_", StringComparison.OrdinalIgnoreCase))
				{
					ByPrefab[StringExtensionMethods.GetStableHashCode(((Object)prefab2).name)] = value2;
				}
				else if (!((Object)(object)prefab2.GetComponent<Piece>() != (Object)null))
				{
					if (WildBeehive(prefab2))
					{
						ByPrefab[StringExtensionMethods.GetStableHashCode(((Object)prefab2).name)] = Add("beehive", "Beehive", "$piece_beehive", Kind.Beehive, (Biome)1, on: true, 0f, 15f, "Honey");
					}
					else if ((Object)(object)prefab2.GetComponent<SpawnArea>() != (Object)null || (Object)(object)prefab2.GetComponent<CreatureSpawner>() != (Object)null)
					{
						AddSpawner(prefab2, value3, creatures);
					}
					else if ((Object)(object)prefab2.GetComponent<MineRock5>() != (Object)null || (Object)(object)prefab2.GetComponent<MineRock>() != (Object)null || (Object)(object)Fractured(prefab2) != (Object)null || Props.Contains(((Object)prefab2).name))
					{
						AddDeposit(prefab2, value3, insideLocations: true);
					}
				}
			}
		}

		private static void AddVegetation(GameObject prefab, Biome biome)
		{
			//IL_0142: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			Pickable component = prefab.GetComponent<Pickable>();
			if ((Object)(object)component != (Object)null && (Object)(object)component.m_itemPrefab != (Object)null)
			{
				ItemDrop component2 = component.m_itemPrefab.GetComponent<ItemDrop>();
				if (!((Object)(object)component2 == (Object)null))
				{
					Thing thing = Add("plant:" + ((Object)component2).name, Localized(component2.m_itemData.m_shared.m_name, Pretty(((Object)component2).name)), component2.m_itemData.m_shared.m_name, Kind.Plant, biome, !Plain.Contains(((Object)component2).name), component.m_respawnTimeMinutes, 12f, ((Object)component2).name);
					ByPrefab[StringExtensionMethods.GetStableHashCode(((Object)prefab).name)] = thing;
					Named(component.m_overrideName, thing);
				}
			}
			else
			{
				Beehive component3 = prefab.GetComponent<Beehive>();
				if ((Object)(object)component3 != (Object)null)
				{
					ByPrefab[StringExtensionMethods.GetStableHashCode(((Object)prefab).name)] = Add("beehive", "Beehive", string.IsNullOrEmpty(component3.m_name) ? "$piece_beehive" : component3.m_name, Kind.Beehive, biome, on: true, 0f, 15f, "Honey");
				}
				else if ((Object)(object)prefab.GetComponent<SpawnArea>() != (Object)null)
				{
					AddSpawner(prefab, biome, null);
				}
				else
				{
					AddDeposit(prefab, biome, insideLocations: false);
				}
			}
		}

		private static bool WildBeehive(GameObject prefab)
		{
			return (prefab.GetComponent<DropOnDestroyed>()?.m_dropWhenDestroyed?.m_drops)?.Any((DropData drop) => (Object)(object)drop.m_item != (Object)null && ((Object)drop.m_item).name == "QueenBee") ?? false;
		}

		private static Dictionary<string, Biome> CreatureHomes(ZoneSystem zones)
		{
			//IL_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: 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)
			Dictionary<string, Biome> homes = new Dictionary<string, Biome>();
			SpawnSystem val = (((Object)(object)zones.m_zoneCtrlPrefab != (Object)null) ? zones.m_zoneCtrlPrefab.GetComponent<SpawnSystem>() : null);
			if (val?.m_spawnLists == null)
			{
				return homes;
			}
			foreach (SpawnSystemList spawnList in val.m_spawnLists)
			{
				if (spawnList?.m_spawners == null)
				{
					continue;
				}
				foreach (SpawnData spawner in spawnList.m_spawners)
				{
					if (spawner != null && spawner.m_enabled && (Object)(object)spawner.m_prefab != (Object)null)
					{
						homes[((Object)spawner.m_prefab).name] = (Biome)((homes.TryGetValue(((Object)spawner.m_prefab).name, out var value) ? ((int)value) : 0) | (spawner.m_biome & AllBiomes));
					}
				}
			}
			foreach (string name in homes.Keys.ToList())
			{
				if (Biomes.Count((Biome biome) => (homes[name] & biome) > 0) > 3)
				{
					homes[name] = (Biome)0;
				}
			}
			return homes;
		}

		private static void AddSpawner(GameObject prefab, Biome biome, Dictionary<string, Biome> creatures)
		{
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			int stableHashCode = StringExtensionMethods.GetStableHashCode(((Object)prefab).name);
			GameObject val = prefab.GetComponent<SpawnArea>()?.m_prefabs?.Select((SpawnData data) => data?.m_prefab).FirstOrDefault((Func<GameObject, bool>)((GameObject p) => (Object)(object)p != (Object)null && (Object)(object)p.GetComponent<Character>() != (Object)null)) ?? prefab.GetComponent<CreatureSpawner>()?.m_creaturePrefab;
			string text = ((!((Object)(object)val != (Object)null)) ? null : val.GetComponent<Character>()?.m_name);
			if (string.IsNullOrEmpty(text))
			{
				ByPrefab[stableHashCode] = Get("spawner");
				return;
			}
			if ((int)biome == 0)
			{
				creatures?.TryGetValue(((Object)val).name, out biome);
			}
			GameObject val2 = val.GetComponent<CharacterDrop>()?.m_drops?.Select((Drop drop) => drop?.m_prefab).FirstOrDefault((Func<GameObject, bool>)((GameObject p) => (Object)(object)p != (Object)null && ((Object)p).name.StartsWith("Trophy", StringComparison.Ordinal)));
			Thing thing = Add("spawner:" + text.TrimStart(new char[1] { '$' }), Localized(text, Pretty(((Object)val).name)) + " spawner", text, Kind.Spawner, biome, !TameCreatures.Contains(text), 0f, 20f, null);
			if (thing.IconItem == null && (Object)(object)val2 != (Object)null)
			{
				thing.IconItem = ((Object)val2).name;
			}
			ByPrefab[stableHashCode] = thing;
		}

		internal static void ForgetUnknownSpawners()
		{
			foreach (Record item in Records.All)
			{
				if (item.Thing.StartsWith("spawner:", StringComparison.Ordinal) && !ById.ContainsKey(item.Thing))
				{
					item.Thing = "spawner";
					Records.Dirty = true;
				}
			}
		}

		private static void AddPickup(GameObject prefab, Pickable pickable, Biome biome)
		{
			//IL_0039: 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)
			ItemDrop val = (((Object)(object)pickable.m_itemPrefab != (Object)null) ? pickable.m_itemPrefab.GetComponent<ItemDrop>() : null);
			if (!((Object)(object)val == (Object)null) && !Plain.Contains(((Object)val).name))
			{
				if ((int)biome == 0)
				{
					Homes.TryGetValue(((Object)val).name, out biome);
				}
				string name = val.m_itemData.m_shared.m_name;
				Thing thing = Add("plant:" + ((Object)val).name, Localized(name, Pretty(((Object)val).name)), name, Kind.Plant, biome, !Minor.Contains(((Object)val).name), pickable.m_respawnTimeMinutes, 12f, ((Object)val).name);
				ByPrefab[StringExtensionMethods.GetStableHashCode(((Object)prefab).name)] = thing;
				Named(pickable.m_overrideName, thing);
			}
		}

		private static void AddDeposit(GameObject prefab, Biome biome, bool insideLocations)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			string name;
			GameObject fractured;
			ItemDrop val = NotableDrop(prefab, out name, out fractured);
			if (!((Object)(object)val == (Object)null))
			{
				if (insideLocations && (int)biome == 0)
				{
					Homes.TryGetValue(((Object)val).name, out biome);
				}
				bool flag = name?.StartsWith("$piece_", StringComparison.Ordinal) ?? false;
				Thing value = Add("deposit:" + (flag ? name.Substring(7) : ((Object)val).name), Localized(flag ? name : val.m_itemData.m_shared.m_name, Pretty(((Object)val).name)), string.IsNullOrEmpty(name) ? val.m_itemData.m_shared.m_name : name, Kind.Deposit, biome, !Minor.Contains(((Object)val).name), 0f, 10f, ((Object)val).name);
				ByPrefab[StringExtensionMethods.GetStableHashCode(((Object)prefab).name)] = value;
				if ((Object)(object)fractured != (Object)null)
				{
					ByPrefab[StringExtensionMethods.GetStableHashCode(((Object)fractured).name)] = value;
				}
			}
		}

		private static GameObject Fractured(GameObject prefab)
		{
			GameObject val = prefab.GetComponent<Destructible>()?.m_spawnWhenDestroyed;
			if (!((Object)(object)val != (Object)null) || (!((Object)(object)val.GetComponent<MineRock5>() != (Object)null) && !((Object)(object)val.GetComponent<MineRock>() != (Object)null)))
			{
				return null;
			}
			return val;
		}

		private static ItemDrop NotableDrop(GameObject prefab, out string name, out GameObject fractured)
		{
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			name = null;
			fractured = Fractured(prefab);
			if ((Object)(object)fractured != (Object)null)
			{
				prefab = fractured;
			}
			DropTable val = null;
			MineRock5 component = prefab.GetComponent<MineRock5>();
			MineRock component2 = prefab.GetComponent<MineRock>();
			DropOnDestroyed component3 = prefab.GetComponent<DropOnDestroyed>();
			if ((Object)(object)component != (Object)null)
			{
				val = component.m_dropItems;
				name = component.m_name;
			}
			else if ((Object)(object)component2 != (Object)null)
			{
				val = component2.m_dropItems;
				name = component2.m_name;
			}
			else if ((Object)(object)component3 != (Object)null && (Object)(object)prefab.GetComponent<Destructible>() != (Object)null)
			{
				val = component3.m_dropWhenDestroyed;
			}
			if (val?.m_drops == null)
			{
				return null;
			}
			foreach (DropData drop in val.m_drops)
			{
				ItemDrop val2 = (((Object)(object)drop.m_item != (Object)null) ? drop.m_item.GetComponent<ItemDrop>() : null);
				if ((Object)(object)val2 != (Object)null && !Plain.Contains(((Object)val2).name))
				{
					return val2;
				}
			}
			return null;
		}

		private static string Localized(string token, string fallback)
		{
			if (string.IsNullOrEmpty(token) || token[0] != '$' || Localization.instance == null)
			{
				return fallback;
			}
			string text = NoTags(Localization.instance.Localize(token));
			if (!string.IsNullOrEmpty(text) && text[0] != '[')
			{
				return text;
			}
			return fallback;
		}

		private static void AddLocation(string prefabName, Biome biome)
		{
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			if (Skip.IsMatch(prefabName))
			{
				return;
			}
			string text = Regex.Replace(prefabName, "[_\\d]+$", "");
			if (!Places.TryGetValue(text, out var value) && !Places.TryGetValue(prefabName, out value))
			{
				bool flag = Runestone.IsMatch(text);
				value = new Known
				{
					Name = (flag ? "Runestone" : Pretty(Regex.Replace(text, "^(Mistlands|Ashlands|AshLands|DeepNorth|Meadows|BlackForest|Swamp|Mountain|Plains)_", ""))),
					On = (flag || Dungeon.IsMatch(text))
				};
				if (flag)
				{
					text = "Runestone";
				}
			}
			ByLocation[prefabName] = Add("place:" + text, value.Name, value.Label ?? value.Name, Kind.Place, biome, value.On, 0f, 40f, value.Icon);
		}

		private static Thing Add(string id, string name, string label, Kind kind, Biome biome, bool on, float respawn, float spacing, string icon)
		{
			//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_006b: 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_0032: 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_003b: Unknown result type (might be due to invalid IL or missing references)
			if (ById.TryGetValue(id, out var value))
			{
				if (_building && Fresh.Add(id))
				{
					value.Label = label;
					value.Kind = kind;
					value.Biomes = (Biome)(biome | value.Learned);
					value.DefaultOn = on;
					value.RespawnMinutes = respawn;
					value.Spacing = spacing;
					value.IconItem = icon;
				}
				else
				{
					Thing thing = value;
					thing.Biomes |= biome;
				}
				return value;
			}
			if (_building)
			{
				Fresh.Add(id);
			}
			value = new Thing
			{
				Id = id,
				Name = name,
				Label = label,
				Kind = kind,
				Biomes = biome,
				DefaultOn = on,
				RespawnMinutes = respawn,
				Spacing = spacing,
				IconItem = icon
			};
			ById[id] = value;
			Named(name, value);
			Named(label, value);
			return value;
		}

		private static void Named(string name, Thing thing)
		{
			if (!string.IsNullOrEmpty(name) && !ByName.ContainsKey(name))
			{
				ByName[name] = thing;
			}
		}

		internal static Thing ForName(string name)
		{
			if (string.IsNullOrEmpty(name) || !ByName.TryGetValue(name, out var value))
			{
				return null;
			}
			return value;
		}

		private static string NoTags(string text)
		{
			if (text != null)
			{
				return Regex.Replace(text, "<[^>]*>", "");
			}
			return null;
		}

		private static string Pretty(string name)
		{
			string input = Regex.Replace(name.Replace('_', ' '), "(?<=[a-z])(?=[A-Z])|(?<=[A-Za-z])(?=\\d)", " ").Trim();
			input = Regex.Replace(input, "\\s+", " ");
			if (input.Length != 0)
			{
				return char.ToUpperInvariant(input[0]) + input.Substring(1).ToLowerInvariant();
			}
			return name;
		}

		internal static Thing ForPrefab(int prefabHash)
		{
			if (!ByPrefab.TryGetValue(prefabHash, out var value))
			{
				return null;
			}
			return value;
		}

		internal static Thing ForLocation(string prefabName)
		{
			if (!ByLocation.TryGetValue(prefabName, out var value))
			{
				return null;
			}
			return value;
		}

		internal static Thing Get(string id)
		{
			if (id == null || !ById.TryGetValue(id, out var value))
			{
				return null;
			}
			return value;
		}

		private static int IndexOf(Biome biome)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between I4 and Unknown
			for (int i = 0; i < Biomes.Length; i++)
			{
				if ((int)Biomes[i] == (int)biome)
				{
					return i;
				}
			}
			return 0;
		}

		private static void BindThing(Biome biome, Thing thing)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Expected O, but got Unknown
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Expected O, but got Unknown
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0265: Expected O, but got Unknown
			int num = IndexOf(biome);
			if (thing.Slots[num] == null)
			{
				biome = Biomes[num];
				Slot slot = new Slot();
				string text = Section(biome);
				string text2 = thing.Name;
				if (!UsedKeys.Add(text + "|" + text2))
				{
					text2 = thing.Name + " (" + ((thing.Kind == Kind.Plant) ? "pickup" : thing.Kind.ToString().ToLowerInvariant()) + ")";
					UsedKeys.Add(text + "|" + text2);
				}
				ConfigEntry<bool> val = _config.Bind(text, text2, Defaults.On(biome, thing), new ConfigDescription("Pin " + thing.Name.ToLowerInvariant() + " found in the " + BiomeName(biome) + ".", (AcceptableValueBase)null, new object[1]
				{
					new ConfigurationManagerAttributes
					{
						CustomDrawer = delegate(ConfigEntryBase e)
						{
							Icons.DrawSwitch(e, thing, slot);
						}
					}
				}));
				ConfigEntry<Color> val2 = _config.Bind<Color>(text, text2 + " color", thing.AutoColor, new ConfigDescription("Colour of the " + thing.Name.ToLowerInvariant() + " pin in the " + BiomeName(biome) + " with the white icon style.", (AcceptableValueBase)null, new object[1]
				{
					new ConfigurationManagerAttributes
					{
						IsAdvanced = true
					}
				}));
				val.SettingChanged += delegate
				{
					Catalog.Changed?.Invoke();
				};
				ConfigEntry<string> val3 = _config.Bind(text, text2 + " icon", "", new ConfigDescription("Icon of the " + thing.Name.ToLowerInvariant() + " pin in the " + BiomeName(biome) + ": empty = by the icon style, \"game\" = its game icon, else a white icon's name. Picked by clicking its icon in F1.", (AcceptableValueBase)null, new object[1]
				{
					new ConfigurationManagerAttributes
					{
						Browsable = false
					}
				}));
				val2.SettingChanged += delegate
				{
					Catalog.Recolored?.Invoke();
				};
				val3.SettingChanged += delegate
				{
					Catalog.Changed?.Invoke();
				};
				slot.Toggle = val;
				slot.Color = val2;
				slot.Icon = val3;
				thing.Slots[num] = slot;
			}
		}

		internal static bool IsOn(Biome biome, Thing thing)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0041: 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_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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)
			if (thing == null)
			{
				return false;
			}
			int num = IndexOf(biome);
			if (thing.Slots[num] == null)
			{
				BindThing(Biomes[num], thing);
				if ((thing.Biomes & Biomes[num]) == 0)
				{
					thing.Biomes |= Biomes[num];
					thing.Learned |= Biomes[num];
					_cacheDirty = Built;
				}
			}
			return thing.Slots[num].Toggle.Value;
		}

		internal static Color ColorOf(Biome biome, Thing thing)
		{
			//IL_000c: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			return ((thing != null) ? thing.Slots[IndexOf(biome)] : null)?.Color.Value ?? thing?.AutoColor ?? Color.white;
		}

		internal static string IconChoice(Biome biome, Thing thing)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			if (thing == null)
			{
				return null;
			}
			return thing.Slots[IndexOf(biome)]?.Icon.Value;
		}

		static Catalog()
		{
			Biome[] array = new Biome[9];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			Biomes = (Biome[])(object)array;
			Bosses = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "place:Eikthyrnir", "place:GDKing", "place:Bonemass", "place:Dragonqueen", "place:GoblinKing", "place:Mistlands_DvergrBossEntrance", "place:FaderLocation" };
			Dungeon = new Regex("(Crypt|Cave|Cavern|Mine|Hole|Tunnel|Dungeon|Fortress|Tomb|Dvergr)", RegexOptions.IgnoreCase);
			Camp = new Regex("(Camp|Village)", RegexOptions.IgnoreCase);
			Plain = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
			{
				"Wood", "FineWood", "RoundLog", "ElderBark", "YggdrasilWood", "Blackwood", "Stone", "Flint", "Resin", "Grausten",
				"Feathers", "BoneFragments", "StoneRock", "Snowball", "FirCone"
			};
			Minor = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
			{
				"Lantern", "Tankard_dvergr", "FishingRod", "Wisp", "FaderEmber", "Turnip", "Carrot", "Onion", "Kale", "Poteitr",
				"OatSeeds", "Coal"
			};
			Homes = new Dictionary<string, Biome>(StringComparer.OrdinalIgnoreCase)
			{
				["SurtlingCore"] = (Biome)8,
				["Guck"] = (Biome)2,
				["IronScrap"] = (Biome)2,
				["DragonEgg"] = (Biome)4,
				["Crystal"] = (Biome)4,
				["Obsidian"] = (Biome)4,
				["WolfHairBundle"] = (Biome)4,
				["GoblinTotem"] = (Biome)16,
				["Tar"] = (Biome)16,
				["Barley"] = (Biome)16,
				["Flax"] = (Biome)16,
				["BlackCore"] = (Biome)512,
				["RoyalJelly"] = (Biome)512,
				["Softtissue"] = (Biome)512,
				["Coins"] = (Biome)512,
				["Lantern"] = (Biome)512,
				["Tankard_dvergr"] = (Biome)512,
				["MoltenCore"] = (Biome)32,
				["SulfurStone"] = (Biome)32,
				["VoltureEgg"] = (Biome)32,
				["BellFragment"] = (Biome)32,
				["FlametalOreNew"] = (Biome)32,
				["GoldOre"] = (Biome)64
			};
			TameCreatures = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "$enemy_chicken", "$enemy_hen", "$animal_fish4", "$animal_fish4_cave" };
			Builds = new string[1] { "piece_sapcollector" };
			Props = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { "GuckSack", "GuckSack_small", "Charred_altar_bellfragment" };
			Places = new Dictionary<string, Known>(StringComparer.OrdinalIgnoreCase)
			{
				["Crypt"] = new Known
				{
					Name = "Burial Chambers",
					Icon = "TrophySkeleton"
				},
				["SunkenCrypt"] = new Known
				{
					Name = "Crypt",
					Icon = "TrophyDraugr"
				},
				["TrollCave"] = new Known
				{
					Name = "Troll Cave",
					Icon = "TrophyFrostTroll"
				},
				["MountainCave"] = new Known
				{
					Name = "Frost Cave",
					Icon = "TrophyCultist"
				},
				["Mistlands_DvergrTownEntrance"] = new Known
				{
					Name = "Infested Mine",
					Icon = "TrophySeeker"
				},
				["CharredFortress"] = new Known
				{
					Name = "Charred Fortress",
					Icon = "TrophyCharredMelee"
				},
				["MorgenHole"] = new Known
				{
					Name = "Putrid Hole",
					Icon = "TrophyMorgen"
				},
				["Hildir_crypt"] = new Known
				{
					Name = "Smouldering Tomb",
					Icon = "TrophySkeletonHildir"
				},
				["Hildir_cave"] = new Known
				{
					Name = "Howling Cavern",
					Icon = "TrophyCultist_Hildir"
				},
				["Hildir_plainsfortress"] = new Known
				{
					Name = "Sealed Tower",
					Icon = "TrophyGoblinBruteBrosBrute"
				},
				["Eikthyrnir"] = new Known
				{
					Name = "Eikthyr altar",
					Label = "Eikthyr",
					Icon = "TrophyEikthyr"
				},
				["GDKing"] = new Known
				{
					Name = "The Elder altar",
					Label = "The Elder",
					Icon = "TrophyTheElder"
				},
				["Bonemass"] = new Known
				{
					Name = "Bonemass altar",
					Label = "Bonemass",
					Icon = "TrophyBonemass"
				},
				["Dragonqueen"] = new Known
				{
					Name = "Moder altar",
					Label = "Moder",
					Icon = "TrophyDragonQueen"
				},
				["GoblinKing"] = new Known
				{
					Name = "Yagluth altar",
					Label = "Yagluth",
					Icon = "TrophyGoblinKing"
				},
				["Mistlands_DvergrBossEntrance"] = new Known
				{
					Name = "The Queen altar",
					Label = "The Queen",
					Icon = "TrophySeekerQueen"
				},
				["FaderLocation"] = new Known
				{
					Name = "Fader altar",
					Label = "Fader",
					Icon = "TrophyFader"
				},
				["Vendor_BlackForest"] = new Known
				{
					Name = "Haldor",
					Icon = "Coins"
				},
				["Hildir_camp"] = new Known
				{
					Name = "Hildir",
					Icon = "Coins"
				},
				["BogWitch_Camp"] = new Known
				{
					Name = "Bog Witch",
					Icon = "Coins"
				},
				["GoblinCamp"] = new Known
				{
					Name = "Fuling village",
					Icon = "TrophyGoblin"
				},
				["WoodVillage"] = new Known
				{
					Name = "Draugr village",
					Icon = "TrophyDraugr"
				},
				["WoodFarm"] = new Known
				{
					Name = "Abandoned farm",
					Icon = "TrophyDraugr"
				},
				["TarPit"] = new Known
				{
					Name = "Tar pit",
					Icon = "Tar"
				},
				["DrakeNest"] = new Known
				{
					Name = "Drake nest",
					Icon = "DragonEgg"
				},
				["InfestedTree"] = new Known
				{
					Name = "Guck tree",
					Icon = "Guck"
				},
				["Mistlands_Giant"] = new Known
				{
					Name = "Giant remains",
					Icon = "Softtissue"
				},
				["PlaceofMystery"] = new Known
				{
					Name = "Place of Mystery"
				},
				["Mistlands_Excavation"] = new Known
				{
					Name = "Dvergr excavation",
					Icon = "BlackCore"
				},
				["Mistlands_Harbour"] = new Known
				{
					Name = "Dvergr harbour",
					Icon = "BlackCore"
				},
				["Mistlands_GuardTower"] = new Known
				{
					Name = "Dvergr tower",
					Icon = "BlackCore"
				}
			};
			Skip = new Regex("^(StartTemple|Meteorite|Vegvisir_.*Placeholder)", RegexOptions.IgnoreCase);
			Runestone = new Regex("^(Runestone|Vegvisir)", RegexOptions.IgnoreCase);
			Fresh = new HashSet<string>();
		}
	}
	internal static class Lairs
	{
		private const float Cell = 64f;

		private const float MaxRadius = 60f;

		private static readonly Dictionary<long, List<Vector4>> Grid = new Dictionary<long, List<Vector4>>();

		private static int _count = -1;

		private static long CellOf(float x, float z)
		{
			return ((long)Mathf.FloorToInt(x / 64f) << 32) ^ (uint)Mathf.FloorToInt(z / 64f);
		}

		internal static void Reset()
		{
			Grid.Clear();
			_count = -1;
		}

		internal static bool Near(Vector3 pos)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			Refresh();
			int num = Mathf.FloorToInt(pos.x / 64f);
			int num2 = Mathf.FloorToInt(pos.z / 64f);
			for (int i = num - 1; i <= num + 1; i++)
			{
				for (int j = num2 - 1; j <= num2 + 1; j++)
				{
					if (!Grid.TryGetValue(((long)i << 32) ^ (uint)j, out var value))
					{
						continue;
					}
					foreach (Vector4 item in value)
					{
						float num3 = item.x - pos.x;
						float num4 = item.y - pos.z;
						if (num3 * num3 + num4 * num4 <= item.z * item.z)
						{
							return true;
						}
					}
				}
			}
			return false;
		}

		private static void Refresh()
		{
			//IL_005b: 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_0061: 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_00a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: 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_00e3: 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_00ee: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			ZoneSystem instance = ZoneSystem.instance;
			if ((Object)(object)instance == (Object)null || !Catalog.Built || instance.m_locationInstances.Count == _count)
			{
				return;
			}
			_count = instance.m_locationInstances.Count;
			Grid.Clear();
			foreach (LocationInstance value2 in instance.m_locationInstances.Values)
			{
				ZoneLocation location = value2.m_location;
				if (location != null && Catalog.IsLair(Catalog.ForLocation(location.m_prefabName)))
				{
					float num = Mathf.Clamp(location.m_exteriorRadius + 10f, 25f, 60f);
					long key = CellOf(value2.m_position.x, value2.m_position.z);
					if (!Grid.TryGetValue(key, out var value))
					{
						value = (Grid[key] = new List<Vector4>());
					}
					value.Add(new Vector4(value2.m_position.x, value2.m_position.z, num, 0f));
				}
			}
		}
	}
	internal sealed class ConfigurationManagerAttributes
	{
		public int? Order;

		public bool? IsAdvanced;

		public bool? Browsable;

		public bool? HideDefaultButton;

		public Action<ConfigEntryBase> CustomDrawer;
	}
	internal static class Defaults
	{
		private static readonly Dictionary<string, bool> Switches = new Dictionary<string, bool>
		{
			["AshLands|place:CharredTowerRuins1_dvergr"] = false,
			["AshLands|deposit:FlametalOreNew"] = false,
			["AshLands|plant:MoltenCore"] = false,
			["AshLands|plant:Pot_Shard_Green"] = false,
			["AshLands|plant:SulfurStone"] = false,
			["AshLands|chest"] = false,
			["AshLands|plant:VoltureEgg"] = false,
			["BlackForest|plant:Blueberries"] = false,
			["BlackForest|deposit:deposit_copper"] = false,
			["BlackForest|plant:Mushroom"] = false,
			["BlackForest|spawner:enemy_skeleton"] = false,
			["BlackForest|plant:Thistle"] = false,
			["BlackForest|deposit:TinOre"] = false,
			["BlackForest|plant:TinOre"] = false,
			["BlackForest|chest"] = false,
			["DeepNorth|place:DN_Bossroom"] = true,
			["DeepNorth|place:DN_gammeltrollFrac"] = true,
			["DeepNorth|deposit:Ice"] = false,
			["DeepNorth|plant:KaleSeeds"] = false,
			["DeepNorth|plant:Lingonberry"] = false,
			["DeepNorth|place:LumberCamp"] = true,
			["DeepNorth|place:NorthVillage"] = true,
			["DeepNorth|deposit:deposit_goldvein"] = false,
			["DeepNorth|place:Runestone"] = false,
			["DeepNorth|spawner:enemy_shadowperson"] = false,
			["DeepNorth|deposit:Frostwood"] = false,
			["DeepNorth|plant:Frostwood"] = false,
			["DeepNorth|chest"] = false,
			["Meadows|place:WoodFarm"] = false,
			["Meadows|deposit:deposit_copper"] = false,
			["Meadows|plant:Dandelion"] = false,
			["Meadows|plant:Mushroom"] = false,
			["Meadows|plant:Raspberry"] = false,
			["Meadows|place:Runestone"] = false,
			["Meadows|spawner:enemy_skeleton"] = false,
			["Meadows|deposit:TinOre"] = false,
			["Meadows|chest"] = false,
			["Mistlands|deposit:giant_helmet"] = false,
			["Mistlands|deposit:giant_sword"] = false,
			["Mistlands|plant:Coins"] = false,
			["Mistlands|spawner:enemy_dvergr_mage"] = false,
			["Mistlands|spawner:enemy_dvergr"] = false,
			["Mistlands|place:Mistlands_Giant"] = false,
			["Mistlands|plant:MushroomJotunPuffs"] = false,
			["Mistlands|plant:MushroomMagecap"] = false,
			["Mistlands|deposit:giant_bone"] = false,
			["Mistlands|plant:RoyalJelly"] = false,
			["Mistlands|spawner:enemy_seekerbrute"] = false,
			["Mistlands|deposit:giant_brain"] = false,
			["Mistlands|spawner:enemy_tick"] = false,
			["Mistlands|chest"] = false,
			["Mountain|deposit:Obsidian"] = false,
			["Mountain|plant:Obsidian"] = false,
			["Mountain|place:Runestone"] = false,
			["Mountain|deposit:deposit_silver"] = false,
			["Mountain|deposit:deposit_silvervein"] = false,
			["Mountain|chest"] = false,
			["Ocean|deposit:Chitin"] = false,
			["Ocean|chest"] = false,
			["Plains|plant:Barley"] = false,
			["Plains|plant:Cloudberry"] = false,
			["Plains|plant:Flax"] = false,
			["Plains|chest"] = false,
			["Swamp|plant:IronOre"] = false,
			["Swamp|deposit:mudpile"] = false,
			["Swamp|plant:Mushroom"] = false,
			["Swamp|spawner:enemy_skeleton"] = false,
			["Swamp|plant:Thistle"] = false,
			["Swamp|chest"] = false,
			["Swamp|plant:TurnipSeeds"] = false
		};

		internal unsafe static bool On(Biome biome, Thing thing)
		{
			if (!Switches.TryGetValue(((object)(*(Biome*)(&biome))/*cast due to .constrained prefix*/).ToString() + "|" + thing.Id, out var value))
			{
				return thing.DefaultOn;
			}
			return value;
		}
	}
	internal static class HandPins
	{
		private static readonly HashSet<PinType> Types = new HashSet<PinType>
		{
			(PinType)0,
			(PinType)1,
			(PinType)2,
			(PinType)3,
			(PinType)6
		};

		private static float _armedUntil;

		private static float _countedAt = -10f;

		private static int _count;

		private static string BackupPath
		{
			get
			{
				if (Records.Key != null)
				{
					return Path.Combine(Records.Folder, Records.Key + ".hand-pins.txt");
				}
				return null;
			}
		}

		private static List<PinData> Find()
		{
			return MapPins.GamePins()?.Where((PinData pin) => pin.m_save && Types.Contains(pin.m_type)).ToList() ?? new List<PinData>();
		}

		internal static void Draw(ConfigEntryBase entry)
		{
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			if ((Object)(object)Minimap.instance == (Object)null || Records.Key == null)
			{
				GUILayout.Label("Load a world first.", Array.Empty<GUILayoutOption>());
				GUILayout.EndHorizontal();
				return;
			}
			if (Time.unscaledTime - _countedAt > 1f)
			{
				_count = Find().Count;
				_countedAt = Time.unscaledTime;
			}
			bool flag = Time.unscaledTime < _armedUntil;
			bool enabled = GUI.enabled;
			GUI.enabled = enabled && _count > 0;
			if (GUILayout.Button(flag ? $"Sure? Click again to remove {_count}" : $"Remove all ({_count})", Array.Empty<GUILayoutOption>()))
			{
				if (flag)
				{
					Remove();
				}
				else
				{
					_armedUntil = Time.unscaledTime + 5f;
				}
			}
			GUI.enabled = enabled && File.Exists(BackupPath);
			if (GUILayout.Button("Bring back", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }))
			{
				Restore();
			}
			GUI.enabled = enabled;
			GUILayout.EndHorizontal();
		}

		private static void Remove()
		{
			_armedUntil = 0f;
			_countedAt = -10f;
			List<PinData> list = Find();
			CultureInfo c = CultureInfo.InvariantCulture;
			try
			{
				File.AppendAllLines(BackupPath, list.Select((PinData pin) => string.Join("\t", ((object)Unsafe.As<PinType, PinType>(ref pin.m_type)/*cast due to .constrained prefix*/).ToString(), pin.m_pos.x.ToString(c), pin.m_pos.y.ToString(c), pin.m_pos.z.ToString(c), pin.m_checked ? "1" : "0", pin.m_ownerID.ToString(c), (pin.m_name ?? "").Replace('\t', ' ').Replace('\n', ' '))));
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Hand-placed pins not removed, could not keep a copy: " + ex.Message));
				}
				return;
			}
			foreach (PinData item in list)
			{
				Minimap.instance.RemovePin(item);
			}
			ManualLogSource log2 = Plugin.Log;
			if (log2 != null)
			{
				log2.LogInfo((object)$"Removed {list.Count} hand-placed pins (a copy is in {Path.GetFileName(BackupPath)}).");
			}
		}

		private static void Restore()
		{
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_013e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			_countedAt = -10f;
			string backupPath = BackupPath;
			CultureInfo invariantCulture = CultureInfo.InvariantCulture;
			List<PinData> source = Find();
			int num = 0;
			string[] array = File.ReadAllLines(backupPath);
			foreach (string text in array)
			{
				string[] f = text.Split(new char[1] { '\t' });
				if (f.Length >= 7 && Enum.TryParse<PinType>(f[0], out PinType type) && float.TryParse(f[1], NumberStyles.Float, invariantCulture, out var result) && float.TryParse(f[2], NumberStyles.Float, invariantCulture, out var result2) && float.TryParse(f[3], NumberStyles.Float, invariantCulture, out var result3) && long.TryParse(f[5], NumberStyles.Integer, invariantCulture, out var result4))
				{
					Vector3 pos = new Vector3(result, result2, result3);
					if (!source.Any((PinData pin) => pin.m_type == type && pin.m_name == f[6] && Utils.DistanceXZ(pin.m_pos, pos) < 0.5f))
					{
						Minimap.instance.AddPin(pos, type, f[6], true, f[4] == "1", result4, default(PlatformUserID));
						num++;
					}
				}
			}
			File.Delete(backupPath);
			ManualLogSource log = Plugin.Log;
			if (log != null)
			{
				log.LogInfo((object)$"Brought back {num} hand-placed pins.");
			}
		}
	}
	internal static class Icons
	{
		private static readonly Dictionary<Sprite, Sprite> WhiteCopies = new Dictionary<Sprite, Sprite>();

		private static readonly Dictionary<Sprite, Color> Averages = new Dictionary<Sprite, Color>();

		private static readonly MethodInfo GetSprite = AccessTools.Method(typeof(Minimap), "GetSprite", (Type[])null, (Type[])null);

		internal const string GameChoice = "game";

		private static ConfigEntryBase _editing;

		private static string _hexText;

		internal static void Prepare(Thing thing)
		{
			//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)
			thing.Icon = Find(thing.IconItem) ?? PinSprite((PinType)((thing.Kind == Kind.Portal) ? 6 : 3));
			thing.IconTried = true;
			if (!thing.ColorKnown)
			{
				thing.AutoColor = Average(thing.Icon);
				thing.ColorKnown = true;
			}
		}

		internal static Sprite Find(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return null;
			}
			GameObject val = (((Object)(object)ObjectDB.instance != (Object)null) ? ObjectDB.instance.GetItemPrefab(name) : null);
			ItemDrop val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<ItemDrop>() : null);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2.m_itemData.GetIcon();
			}
			val = (((Object)(object)ZNetScene.instance != (Object)null) ? ZNetScene.instance.GetPrefab(name) : null);
			Piece val3 = (((Object)(object)val != (Object)null) ? val.GetComponent<Piece>() : null);
			if (!((Object)(object)val3 != (Object)null))
			{
				return null;
			}
			return val3.m_icon;
		}

		internal static Sprite PinSprite(PinType type)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)Minimap.instance == (Object)null || GetSprite == null)
			{
				return null;
			}
			object? obj = GetSprite.Invoke(Minimap.instance, new object[1] { type });
			return (Sprite)((obj is Sprite) ? obj : null);
		}

		internal static Sprite White(Sprite sprite)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: 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_0176: 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_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)sprite == (Object)null)
			{
				return null;
			}
			if (WhiteCopies.TryGetValue(sprite, out var value))
			{
				return value;
			}
			value = sprite;
			Color value2 = Color.white;
			try
			{
				Texture2D val = Read(sprite);
				Color32[] pixels = val.GetPixels32();
				float num = 0f;
				float num2 = 0f;
				float num3 = 0f;
				float num4 = 0f;
				for (int i = 0; i < pixels.Length; i++)
				{
					float num5 = (float)(int)pixels[i].a / 255f;
					if (num5 > 0.3f)
					{
						num += (float)(int)pixels[i].r * num5;
						num2 += (float)(int)pixels[i].g * num5;
						num3 += (float)(int)pixels[i].b * num5;
						num4 += num5;
					}
					pixels[i] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, pixels[i].a);
				}
				val.SetPixels32(pixels);
				val.Apply();
				value = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), sprite.pixelsPerUnit);
				if (num4 > 0f)
				{
					Color val2 = default(Color);
					((Color)(ref val2))..ctor(num / num4 / 255f, num2 / num4 / 255f, num3 / num4 / 255f, 1f);
					float num6 = Mathf.Max(val2.r, Mathf.Max(val2.g, val2.b));
					value2 = (Color)((num6 > 0.05f) ? new Color(val2.r / num6, val2.g / num6, val2.b / num6, 1f) : Color.white);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogWarning((object)("Could not make a white icon from " + ((Object)sprite).name + ": " + ex.Message));
				}
			}
			WhiteCopies[sprite] = value;
			Averages[sprite] = value2;
			return value;
		}

		internal static Color Average(Sprite sprite)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)sprite == (Object)null)
			{
				return Color.white;
			}
			White(sprite);
			if (!Averages.TryGetValue(sprite, out var value))
			{
				return Color.white;
			}
			return value;
		}

		private static Texture2D Read(Sprite sprite)
		{
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: 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_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			Texture2D texture = sprite.texture;
			Rect textureRect = sprite.textureRect;
			int num = Mathf.Max(1, (int)((Rect)(ref textureRect)).width);
			int num2 = Mathf.Max(1, (int)((Rect)(ref textureRect)).height);
			RenderTexture temporary = RenderTexture.GetTemporary(num, num2, 0, (RenderTextureFormat)0);
			RenderTexture active = RenderTexture.active;
			try
			{
				Graphics.Blit((Texture)(object)texture, temporary, new Vector2(((Rect)(ref textureRect)).width / (float)((Texture)texture).width, ((Rect)(ref textureRect)).height / (float)((Texture)texture).height), new Vector2(((Rect)(ref textureRect)).x / (float)((Texture)texture).width, ((Rect)(ref textureRect)).y / (float)((Texture)texture).height));
				RenderTexture.active = temporary;
				Texture2D val = new Texture2D(num, num2, (TextureFormat)4, false);
				val.ReadPixels(new Rect(0f, 0f, (float)num, (float)num2), 0, 0);
				val.Apply();
				return val;
			}
			finally
			{
				RenderTexture.active = active;
				RenderTexture.ReleaseTemporary(temporary);
			}
		}

		internal static Sprite GameIcon(Thing thing)
		{
			return thing.Icon ?? PinSprite((PinType)3);
		}

		internal static Sprite Resolve(Thing thing, Biome biome, bool emptied, out bool tinted)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			tinted = false;
			if (thing != null)
			{
				return Resolve(thing, Catalog.IconChoice(biome, thing), emptied, out tinted);
			}
			return null;
		}

		private static Sprite Resolve(Thing thing, string choice, bool emptied, out bool tinted)
		{
			tinted = false;
			if (choice == "game")
			{
				return GameIcon(thing);
			}
			Sprite val = WhiteIcons.Get(choice);
			if ((Object)(object)val != (Object)null)
			{
				tinted = true;
				return val;
			}
			if (!Plugin.WhiteStyle || (thing.Kind == Kind.Spawner && (Object)(object)thing.Icon != (Object)null))
			{
				return GameIcon(thing);
			}
			tinted = true;
			return (emptied ? WhiteIcons.Get("skoll/open-chest") : null) ?? WhiteFor(thing, choice);
		}

		private static Sprite WhiteFor(Thing thing, string choice)
		{
			return WhiteIcons.Get(choice) ?? WhiteIcons.For(thing) ?? White(GameIcon(thing));
		}

		internal static Sprite PortalIcon(out bool tinted)
		{
			tinted = false;
			string portalIcon = Plugin.PortalIcon;
			if (portalIcon == "game")
			{
				Sprite val = Find("portal_wood");
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			tinted = true;
			return WhiteIcons.Get(portalIcon) ?? WhiteIcons.Get("lorc/magic-portal") ?? PinSprite((PinType)6);
		}

		internal static void DrawSwitch(ConfigEntryBase entry, Thing thing, Slot slot)
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0130: Unknown result type (might be due to invalid IL or missing references)
			//IL_0137: Expected O, but got Unknown
			//IL_0143: 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_01a0: Unknown result type (might be due to invalid IL or missing references)
			object boxedValue = entry.BoxedValue;
			bool flag = default(bool);
			int num;
			if (boxedValue is bool)
			{
				flag = (bool)boxedValue;
				num = 1;
			}
			else
			{
				num = 0;
			}
			bool flag2 = (byte)((uint)num & (flag ? 1u : 0u)) != 0;
			if ((Object)(object)thing.Icon == (Object)null && !thing.IconTried && (Object)(object)ObjectDB.instance != (Object)null)
			{
				thing.IconTried = true;
				thing.Icon = Find(thing.IconItem);
			}
			ConfigEntry<Color> color = slot.Color;
			ConfigEntry<string> icon = slot.Icon;
			string choice = icon?.Value;
			Color val = color?.Value ?? thing.AutoColor;
			Resolve(thing, choice, emptied: false, out var tinted);
			GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			Rect val2 = Square(24f);
			Draw(val2, GameIcon(thing), (Color)(tinted ? new Color(1f, 1f, 1f, 0.35f) : Color.white));
			Rect val3 = Square(24f);
			Draw(val3, WhiteFor(thing, choice), (Color)(tinted ? val : new Color(val.r, val.g, val.b, 0.35f)));
			GUIContent val4 = new GUIContent("", "Click to change the colour and the icon");
			if (GUI.Button(val2, val4, GUIStyle.none) | GUI.Button(val3, val4, GUIStyle.none))
			{
				Toggle(entry);
			}
			bool flag3 = GUILayout.Toggle(flag2, flag2 ? " On" : " Off", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(true) });
			GUILayout.EndHorizontal();
			if (_editing == entry)
			{
				if (color != null)
				{
					DrawColor(color, thing.AutoColor);
				}
				if (icon != null)
				{
					DrawPicker(icon, val, GameIcon(thing));
				}
			}
			GUILayout.EndVertical();
			if (flag3 != flag2)
			{
				entry.BoxedValue = flag3;
			}
		}

		internal static void DrawPortalIcon(ConfigEntryBase entry)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Expected O, but got Unknown
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			if (entry is ConfigEntry<string> val)
			{
				bool tinted;
				Sprite sprite = PortalIcon(out tinted);
				GUILayout.BeginVertical(Array.Empty<GUILayoutOption>());
				GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
				Rect val2 = Square(24f);
				Draw(val2, sprite, tinted ? Plugin.PortalColor : Color.white);
				if (GUI.Button(val2, new GUIContent("", "Click to pick another icon"), GUIStyle.none))
				{
					Toggle(entry);
				}
				GUILayout.Label(string.IsNullOrEmpty(val.Value) ? "Auto" : ((val.Value == "game") ? "Game icon" : IconTitle(val.Value)), Array.Empty<GUILayoutOption>());
				GUILayout.EndHorizontal();
				if (_editing == entry)
				{
					DrawPicker(val, Plugin.PortalColor, Find("portal_wood"));
				}
				GUILayout.EndVertical();
			}
		}

		private static void Toggle(ConfigEntryBase entry)
		{
			_editing = ((_editing == entry) ? null : entry);
			_hexText = null;
		}

		private static Rect Square(float size)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			return GUILayoutUtility.GetRect(size, size, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.Width(size),
				GUILayout.Height(size)
			});
		}

		private static string IconTitle(string name)
		{
			return name.Substring(name.IndexOf('/') + 1).Replace('-', ' ');
		}

		private static void DrawColor(ConfigEntry<Color> entry, Color auto)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: 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_00b0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Invalid comparison between Unknown and I4
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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_00d5: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0145: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: 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_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0221: 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_0254: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: 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)
			Color value = entry.Value;
			string hexText = "#" + ColorUtility.ToHtmlStringRGBA(value);
			Color val = default(Color);
			if (_hexText == null || (ColorUtility.TryParseHtmlString(_hexText, ref val) && val != value))
			{
				_hexText = hexText;
			}
			Color val2 = value;
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			string text = GUILayout.TextField(_hexText, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.Width(100f) });
			if (text != _hexText)
			{
				_hexText = text;
				Color val3 = default(Color);
				if (ColorUtility.TryParseHtmlString(text, ref val3))
				{
					val2 = val3;
				}
			}
			Rect rect = GUILayoutUtility.GetRect(40f, 20f, (GUILayoutOption[])(object)new GUILayoutOption[2]
			{
				GUILayout.ExpandWidth(true),
				GUILayout.Height(20f)
			});
			if ((int)Event.current.type == 7)
			{
				Color color = GUI.color;
				GUI.color = new Color(value.r, value.g, value.b, 1f);
				GUI.DrawTexture(rect, (Texture)(object)Texture2D.whiteTexture);
				GUI.color = color;
			}
			if (GUILayout.Button("Reset", (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) }))
			{
				val2 = auto;
			}
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			val2.r = Number("R", val2.r);
			val2.g = Number("G", val2.g);
			val2.b = Number("B", val2.b);
			val2.a = Number("A", val2.a);
			GUILayout.EndHorizontal();
			GUILayout.BeginHorizontal(Array.Empty<GUILayoutOption>());
			val2.r = GUILayout.HorizontalSlider(val2.r, 0f, 1f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(30f) });
			val2.g = GUILayout.HorizontalSlider(val2.g, 0f, 1f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(30f) });
			val2.b = GUILayout.HorizontalSlider(val2.b, 0f, 1f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(30f) });
			val2.a = GUILayout.HorizontalSlider(val2.a, 0f, 1f, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(30f) });
			GUILayout.EndHorizontal();
			if (val2 != value)
			{
				entry.Value = val2;
			}
		}

		private static float Number(string label, float value)
		{
			GUILayout.Label(label, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.ExpandWidth(false) });
			string text = value.ToString("0.000", CultureInfo.InvariantCulture);
			string text2 = GUILayout.TextField(text, (GUILayoutOption[])(object)new GUILayoutOption[1] { GUILayout.MinWidth(45f) });
			if (!(text2 != text) || !float.TryParse(text2, NumberStyles.Float, CultureInfo.InvariantCulture, out var result))
			{
				return value;
			}
			return Mathf.Clamp01(result);
		}

		private static void DrawPicker(ConfigEntry<string> entry, Color tint, Sprite game)
		{
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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_0095: Expected O, but got Unknown
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknow