Decompiled source of SeneaL UI Unlocker v1.1.1

SeneaLUIUnlocker.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.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SeneaLUI;
using SeneaLUI.Components;
using SeneaLUI.Core;
using SeneaLUI.Hud;
using SeneaLUI.Inv;
using SeneaLUI.Map;
using SeneaLUI.Net;
using SeneaLUI.Patches;
using SeneaLUI.Theme;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.Rendering;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: IgnoresAccessChecksTo("SeneaL-UI")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("SeneaLUIUnlocker")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+451f989c3bd01a2c60337d6c4277b6434ef2ce2a")]
[assembly: AssemblyProduct("SeneaLUIUnlocker")]
[assembly: AssemblyTitle("SeneaLUIUnlocker")]
[assembly: InternalsVisibleTo("SeneaLUIUnlocker.WindowAdditions")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SeneaLUIUnlocker
{
	internal static class Accessibility
	{
		[HarmonyPatch(typeof(Hud), "DamageFlash")]
		internal static class FlashPatch
		{
			private static bool Prefix()
			{
				if (_flash != null)
				{
					return _flash.Value;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(GameCamera), "AddShake")]
		internal static class ShakePatch
		{
			private static bool Prefix()
			{
				if (_shake != null)
				{
					return _shake.Value;
				}
				return true;
			}
		}

		[HarmonyPatch(typeof(SmokeRenderer), "LateUpdate")]
		internal static class SmokePatch
		{
			private static void Postfix(SmokeRenderer __instance)
			{
				bool flag = _smoke == null || _smoke.Value;
				foreach (ParticleSystem value in __instance.m_chunkedParticleSystems.Values)
				{
					ParticleSystemRenderer val = (((Object)(object)value == (Object)null) ? null : ((Component)value).GetComponent<ParticleSystemRenderer>());
					if ((Object)(object)val != (Object)null && ((Renderer)val).enabled != flag)
					{
						((Renderer)val).enabled = flag;
					}
				}
			}
		}

		private static ConfigEntry<bool> _shake;

		private static ConfigEntry<bool> _smoke;

		private static ConfigEntry<bool> _flash;

		public static void Bind(ConfigFile cfg)
		{
			_shake = cfg.Bind<bool>("Accessibility", "Camera Shake", true, "The camera shakes from hits, explosions and heavy steps, as the game has it; off keeps it still.");
			_smoke = cfg.Bind<bool>("Accessibility", "Show Smoke", true, "Fires' smoke is drawn, as the game has it. Off hides it, while the smoke itself still gathers under roofs and still smokes you out.");
			_flash = cfg.Bind<bool>("Accessibility", "Damage Flash", true, "The screen flashes red when you are hurt, as the game has it; off keeps it clear.");
		}
	}
	internal static class AreaPreview
	{
		private const int Segments = 96;

		private static ConfigEntry<float> _seconds;

		private static readonly HashSet<(string Section, string Key)> Areas = new HashSet<(string, string)>
		{
			("Auto Pins", "Discover Radius"),
			("Auto Pins", "Resource Patch Radius"),
			("Combat HUD", "Combat Enemy Range"),
			("Party", "Party Key Reach"),
			("Party HUD", "Face Picture Distance"),
			("Fuel Helper", "Fuel Radius"),
			("Cheats: Inventory", "Cycle Chests Range"),
			("Cheats: Map", "Ship Exploration Radius (Cheat)"),
			("Cheats: Map", "Walking Exploration Radius (Cheat)"),
			("Previews", "Area Preview Distance"),
			("Unlocked Limits", "Max Craft Range"),
			("Unlocked Limits", "Max Build Range"),
			("Unlocked Limits", "Max Quick Stack Range"),
			("Unlocked Limits", "Max Area Pickup Radius"),
			("Unlocked Limits", "Max Ore Radius"),
			("Unlocked Limits", "Max Radar Range"),
			("Cheats: Beyond Maximums", "Max Chest Range Beyond"),
			("Cheats: Beyond Maximums", "Max Area Pickup Beyond"),
			("Cheats: Beyond Maximums", "Max Ore Radius Beyond"),
			("Cheats: Beyond Maximums", "Max Radar Range Beyond"),
			("Cheats: Portals", "Tames Through Portals Range"),
			("Tames", "Tame Command Range"),
			("Building", "Build Camera Range"),
			("Building", "Repair Nearby Range"),
			("Doors", "Door Open Distance"),
			("Alerts", "Production Alert Range"),
			("Find In Chests", "Find Range")
		};

		private static LineRenderer _ring;

		private static ConfigEntryBase _entry;

		private static float _until;

		public static void Bind(ConfigFile cfg)
		{
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			_seconds = cfg.Bind<float>("Previews", "Range Preview Seconds", 20f, new ConfigDescription("How long a range drawn by an eye button on the settings page stays around you.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(3f, 120f), Array.Empty<object>()));
		}

		public static bool IsArea(ConfigEntryBase entry)
		{
			return Areas.Contains((entry.Definition.Section, entry.Definition.Key));
		}

		public static bool Showing(ConfigEntryBase entry)
		{
			if (_entry == entry)
			{
				return Time.time < _until;
			}
			return false;
		}

		public static void Toggle(ConfigEntryBase entry)
		{
			if (Showing(entry))
			{
				_until = 0f;
				return;
			}
			_entry = entry;
			_until = Time.time + _seconds.Value;
		}

		public static void Tick()
		{
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dd: 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_00f3: 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)
			Player localPlayer = Player.m_localPlayer;
			if (_entry == null || !(Time.time < _until) || !((Object)(object)localPlayer != (Object)null) || !ServerRules.Allows("Previews"))
			{
				if ((Object)(object)_ring != (Object)null && ((Component)_ring).gameObject.activeSelf)
				{
					((Component)_ring).gameObject.SetActive(false);
				}
				return;
			}
			if ((Object)(object)_ring == (Object)null)
			{
				Build();
			}
			((Component)_ring).gameObject.SetActive(true);
			float num = Convert.ToSingle(_entry.BoxedValue);
			Vector3 position = ((Component)localPlayer).transform.position;
			float num3 = default(float);
			for (int i = 0; i < 96; i++)
			{
				float num2 = (float)i * (float)Math.PI * 2f / 96f;
				Vector3 val = position + new Vector3(Mathf.Cos(num2) * num, 0f, Mathf.Sin(num2) * num);
				val.y = (((Object)(object)ZoneSystem.instance != (Object)null && ZoneSystem.instance.GetGroundHeight(val, ref num3)) ? (num3 + 0.3f) : (position.y + 0.3f));
				_ring.SetPosition(i, val);
			}
		}

		private static void Build()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("SeneaLUIUnlocker_AreaPreview");
			Object.DontDestroyOnLoad((Object)val);
			_ring = val.AddComponent<LineRenderer>();
			_ring.loop = true;
			_ring.positionCount = 96;
			_ring.useWorldSpace = true;
			_ring.widthMultiplier = 0.25f;
			((Renderer)_ring).material = new Material(Shader.Find("Sprites/Default"));
			LineRenderer ring = _ring;
			LineRenderer ring2 = _ring;
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(0.85f, 0.72f, 0.43f, 0.9f);
			ring2.endColor = val2;
			ring.startColor = val2;
			_ring.numCapVertices = 2;
		}
	}
	internal sealed class AutoDoors
	{
		private const string Section = "Doors";

		private static readonly Collider[] Near = (Collider[])(object)new Collider[64];

		private static readonly int Mask = LayerMask.GetMask(new string[3] { "piece", "piece_nonsolid", "Default" });

		private readonly ConfigEntry<bool> _on;

		private readonly ConfigEntry<float> _distance;

		private readonly ConfigEntry<bool> _close;

		private readonly ConfigEntry<float> _delay;

		private readonly Dictionary<Door, float> _opened = new Dictionary<Door, float>();

		private float _next;

		private static readonly List<Character> Characters = new List<Character>();

		public AutoDoors(ConfigFile cfg)
		{
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Expected O, but got Unknown
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Expected O, but got Unknown
			_on = cfg.Bind<bool>("Doors", "Auto Doors", false, "Doors and gates open as you walk up to them, never ones that need a key or sit in a ward that does not admit you. Off by default because it opens doors other players share.");
			_distance = cfg.Bind<float>("Doors", "Door Open Distance", 2.2f, new ConfigDescription("How close to a door, in meters, you walk before it opens.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 5f), Array.Empty<object>()));
			_close = cfg.Bind<bool>("Doors", "Close Doors Behind You", true, "Close a door this opened once you have walked away from it and nobody stands in it.");
			_delay = cfg.Bind<float>("Doors", "Door Close Delay", 1.5f, new ConfigDescription("Seconds after you leave a door before it closes behind you.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.2f, 10f), Array.Empty<object>()));
		}

		public void Tick(float now)
		{
			//IL_0059: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0177: Unknown result type (might be due to invalid IL or missing references)
			//IL_017f: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (!_on.Value || !ServerRules.Allows("AutoDoors") || (Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead())
			{
				_opened.Clear();
			}
			else
			{
				if (now < _next)
				{
					return;
				}
				_next = now + 0.1f;
				Vector3 position = ((Component)localPlayer).transform.position;
				int num = Physics.OverlapSphereNonAlloc(position, _distance.Value, Near, Mask);
				for (int i = 0; i < num; i++)
				{
					Door val = (((Object)(object)Near[i] == (Object)null) ? null : ((Component)Near[i]).GetComponentInParent<Door>());
					if (!((Object)(object)val == (Object)null) && !_opened.ContainsKey(val) && Usable(val) && State(val) == 0)
					{
						Vector3 val2 = position - ((Component)val).transform.position;
						val.Open(((Vector3)(ref val2)).normalized);
						_opened[val] = float.MaxValue;
						Log(val, "opened");
					}
				}
				List<Door> list = new List<Door>();
				foreach (Door item in new List<Door>(_opened.Keys))
				{
					if ((Object)(object)item == (Object)null || !item.m_nview.IsValid() || State(item) == 0)
					{
						list.Add(item);
						continue;
					}
					if (!(Vector3.Distance(position, ((Component)item).transform.position) > _distance.Value + 0.8f))
					{
						_opened[item] = float.MaxValue;
						continue;
					}
					if (_opened[item] == float.MaxValue)
					{
						_opened[item] = now + _delay.Value;
					}
					if (now >= _opened[item] && _close.Value && !Occupied(item))
					{
						item.m_nview.InvokeRPC("UseDoor", new object[1] { true });
						Log(item, "closed");
						list.Add(item);
					}
					else if (!_close.Value)
					{
						list.Add(item);
					}
				}
				foreach (Door item2 in list)
				{
					_opened.Remove(item2);
				}
			}
		}

		private static int State(Door door)
		{
			if (!((Object)(object)door.m_nview != (Object)null) || !door.m_nview.IsValid())
			{
				return 1;
			}
			return door.m_nview.GetZDO().GetInt(ZDOVars.s_state, 0);
		}

		private static bool Usable(Door door)
		{
			//IL_003f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)door.m_nview != (Object)null && door.m_nview.IsValid() && (Object)(object)door.m_keyItem == (Object)null && !door.m_canNotBeClosed)
			{
				if (door.m_checkGuardStone)
				{
					return PrivateArea.CheckAccess(((Component)door).transform.position, 0f, false, false);
				}
				return true;
			}
			return false;
		}

		private static bool Occupied(Door door)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			Characters.Clear();
			Character.GetCharactersInRange(((Component)door).transform.position, 1.6f, Characters);
			return Characters.Count > 0;
		}

		private static void Log(Door door, string what)
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			if (DebugLog.On)
			{
				DebugLog.Write("doors", $"{what} {((Object)door).name} at {((Component)door).transform.position}");
			}
		}
	}
	internal static class AutoPickupIgnore
	{
		[HarmonyPatch(typeof(Player), "AutoPickup")]
		internal static class AutoPickupPatch
		{
			private static void Prefix()
			{
				_inAutoPickup = true;
			}

			private static void Finalizer()
			{
				_inAutoPickup = false;
			}
		}

		[HarmonyPatch(typeof(ItemDrop), "CanPickup")]
		internal static class CanPickupPatch
		{
			private static void Postfix(ItemDrop __instance, ref bool __result)
			{
				if (_inAutoPickup && __result && _set.Count != 0 && ServerRules.Allows("AutoPickupIgnore") && __instance.m_itemData != null)
				{
					ItemData itemData = __instance.m_itemData;
					if (_set.Contains(itemData.m_shared.m_name) || Labels().Contains(Shown(itemData.m_shared.m_name)) || ((Object)(object)itemData.m_dropPrefab != (Object)null && _set.Contains(((Object)itemData.m_dropPrefab).name)))
					{
						__result = false;
					}
				}
			}
		}

		private static ConfigEntry<string> _ignored;

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

		private static bool _inAutoPickup;

		private static HashSet<string> _labels;

		private static HashSet<string> _labelsFor;

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

		public static void Bind(ConfigFile cfg)
		{
			_ignored = cfg.Bind<string>("Auto Pickup", "Never Auto Pickup", "", "Items auto-pickup leaves on the ground; you can still pick them up by hand.");
			_ignored.SettingChanged += delegate
			{
				_set = SettingsPage.Split(_ignored.Value);
			};
			_set = SettingsPage.Split(_ignored.Value);
		}

		private static string Shown(string token)
		{
			if (!ShownCache.TryGetValue(token, out var value))
			{
				value = ((Localization.instance == null) ? token : Localization.instance.Localize(token));
				ShownCache[token] = value;
			}
			return value;
		}

		private static HashSet<string> Labels()
		{
			if (_labelsFor != _set)
			{
				_labelsFor = _set;
				_labels = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
				foreach (string item in _set)
				{
					if (item.StartsWith("$", StringComparison.Ordinal))
					{
						_labels.Add(Shown(item));
					}
				}
			}
			return _labels;
		}
	}
	internal enum DungeonDone
	{
		Key_Pressed,
		All_Chests_Opened,
		Enemies_Cleared,
		Chests_And_Enemies
	}
	internal sealed class AutoPins
	{
		private sealed class Category
		{
			public ConfigEntry<bool> On;

			public ConfigEntry<string> Names;

			public PinType Icon;

			public string Kind;
		}

		private const string Section = "Auto Pins";

		private const string DataKey = "alkeari.senealuiunlocker.autopins";

		private const string DoneKey = "alkeari.senealuiunlocker.dungeonsdone";

		private static readonly Type OreScout = TypeLookup.Find("SeneaLUI.Map.OreScout");

		private static readonly MethodInfo OreWanted = ((OreScout == null) ? null : AccessTools.Method(OreScout, "Wanted", new Type[1] { typeof(string) }, (Type[])null));

		private static readonly PropertyInfo OreDetect = AccessTools.Property(TypeLookup.Find("SeneaLUI.Plugin"), "OreDetect");

		private static readonly PropertyInfo CanOreDetect = AccessTools.Property(TypeLookup.Find("SeneaLUI.Net.Policy"), "CanOreDetect");

		private static readonly FieldInfo SeneaLDungeonType = AccessTools.Field(TypeLookup.Find("SeneaLUI.Map.MapPins"), "Dungeon");

		private const float CheckSeconds = 3f;

		private const float SamePlace = 20f;

		private readonly ConfigEntry<bool> _enabled;

		private readonly ConfigEntry<float> _radius;

		private readonly Category[] _categories;

		private readonly ConfigEntry<bool> _resources;

		private readonly ConfigEntry<string> _resourceItems;

		private readonly ConfigEntry<float> _resourceCluster;

		private readonly ConfigEntry<DungeonDone> _dungeonDone;

		private readonly ConfigEntry<KeyboardShortcut> _doneKey;

		private float _insideSince = -1f;

		private ZoneSystem _audited;

		private readonly ManualLogSource _log;

		private Player _for;

		private HashSet<string> _done = new HashSet<string>();

		private HashSet<string> _dungeonsDone = new HashSet<string>();

		private float _next;

		private int _retypedAt = -1;

		private const float InteriorHeight = 3000f;

		private const float InsideSettleSeconds = 10f;

		private static (string Prefix, string Name, string English)[] KnownNames => new(string, string, string)[19]
		{
			("Mistlands_DvergrBossEntrance", Lang.T("AutoPins.PlaceTheQueen", "The Queen"), "The Queen"),
			("Mistlands_DvergrTownEntrance", Lang.T("AutoPins.PlaceInfestedMine", "Infested Mine"), "Infested Mine"),
			("Hildir_plainsfortress", Lang.T("AutoPins.PlaceSealedTower", "Sealed Tower"), "Sealed Tower"),
			("Vendor_BlackForest", Lang.T("AutoPins.PlaceHaldor", "Haldor"), "Haldor"),
			("FaderLocation", Lang.T("AutoPins.PlaceFader", "Fader"), "Fader"),
			("Hildir_crypt", Lang.T("AutoPins.PlaceSmoulderingTomb", "Smouldering Tomb"), "Smouldering Tomb"),
			("BogWitch_Camp", Lang.T("AutoPins.PlaceBogWitch", "Bog Witch"), "Bog Witch"),
			("Hildir_cave", Lang.T("AutoPins.PlaceHowlingCavern", "Howling Cavern"), "Howling Cavern"),
			("Hildir_camp", Lang.T("AutoPins.PlaceHildir", "Hildir"), "Hildir"),
			("SunkenCrypt", Lang.T("AutoPins.PlaceSunkenCrypt", "Sunken Crypt"), "Sunken Crypt"),
			("MountainCave", Lang.T("AutoPins.PlaceFrostCave", "Frost Cave"), "Frost Cave"),
			("Dragonqueen", Lang.T("AutoPins.PlaceModer", "Moder"), "Moder"),
			("Eikthyrnir", Lang.T("AutoPins.PlaceEikthyr", "Eikthyr"), "Eikthyr"),
			("GoblinKing", Lang.T("AutoPins.PlaceYagluth", "Yagluth"), "Yagluth"),
			("GoblinCamp", Lang.T("AutoPins.PlaceFulingVillage", "Fuling Village"), "Fuling Village"),
			("MorgenHole", Lang.T("AutoPins.PlacePutridHole", "Putrid Hole"), "Putrid Hole"),
			("Runestone_", Lang.T("AutoPins.PlaceRunestone", "Runestone"), "Runestone"),
			("GDKing", Lang.T("AutoPins.PlaceTheElder", "The Elder"), "The Elder"),
			("Crypt", Lang.T("AutoPins.PlaceBurialChambers", "Burial Chambers"), "Burial Chambers")
		};

		public AutoPins(ConfigFile cfg, ManualLogSource log)
		{
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Expected O, but got Unknown
			//IL_00b8: 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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_010f: Unknown result type (might be due to invalid IL or missing references)
			//IL_012c: 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_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: Expected O, but got Unknown
			_log = log;
			_enabled = cfg.Bind<bool>("Auto Pins", "Auto Pins", true, "Pin useful places and resources on the map as you come near them.");
			_radius = cfg.Bind<float>("Auto Pins", "Discover Radius", 60f, new ConfigDescription("Distance, meters, within which a place is pinned.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 200f), Array.Empty<object>()));
			_categories = new Category[6]
			{
				Make(cfg, "Boss Altars", "Eikthyrnir; GDKing; Bonemass; Dragonqueen; GoblinKing; Mistlands_DvergrBossEntrance; FaderLocation", (PinType)9),
				Make(cfg, "Traders", "Vendor_BlackForest; Hildir_camp; BogWitch_Camp", PinKinds.Of("Traders")),
				Make(cfg, "Dungeons", "Crypt; SunkenCrypt; TrollCave; MountainCave; Mistlands_DvergrTownEntrance; Hildir_crypt; Hildir_cave; Hildir_plainsfortress; MorgenHole; PlaceofMystery", PinKinds.Of("Dungeons")),
				Make(cfg, "Villages And Camps", "WoodVillage; WoodFarm; GoblinCamp; Greydwarf_camp; StoneTowerRuins; Mistlands_Harbour; Mistlands_Excavation; Mistlands_Giant; CharredFortress; CharredRuins; FortressRuins", PinKinds.Of("Villages And Camps")),
				Make(cfg, "Runestones", "Runestone_; DrakeLorestone", PinKinds.Of("Runestones")),
				Make(cfg, "Nests And Pits", "DrakeNest; TarPit; VoltureNest; InfestedTree", PinKinds.Of("Nests And Pits"))
			};
			_resources = cfg.Bind<bool>("Auto Pins", "Pin Resources", false, "Pin pickable resources listed in Resource Items, one pin per patch. Off by default, since it adds a great many pins.");
			_resourceItems = cfg.Bind<string>("Auto Pins", "Resource Items", "Raspberry; Blueberries; Cloudberry; MushroomYellow; MushroomBlue; MushroomJotunPuffs; MushroomMagecap; Thistle; Flax; Barley; CarrotSeeds; TurnipSeeds; OnionSeeds; DragonEgg; SurtlingCore; Fiddleheadfern; Vineberry", "Pickable items that get a pin, by the item's internal name, separated by semicolons.");
			_dungeonDone = cfg.Bind<DungeonDone>("Auto Pins", "Dungeon Done When", DungeonDone.Key_Pressed, "When a pinned dungeon's pin is crossed out: only when you press Mark Dungeon Done Key, or also on its own once every chest inside is empty, once no living enemy is left inside, or once both are true.");
			_doneKey = cfg.Bind<KeyboardShortcut>("Auto Pins", "Mark Dungeon Done Key", new KeyboardShortcut((KeyCode)107, Array.Empty<KeyCode>()), "Crosses out the pin of the dungeon you are in or standing at, or brings it back if it is crossed out. Works whatever Dungeon Done When says. Empty = no key.");
			_resourceCluster = cfg.Bind<float>("Auto Pins", "Resource Patch Radius", 40f, new ConfigDescription("Resources of one kind within this distance, meters, share one pin.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(5f, 200f), Array.Empty<object>()));
		}

		private static Category Make(ConfigFile cfg, string kind, string names, PinType icon)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			return new Category
			{
				Kind = kind,
				Icon = icon,
				On = cfg.Bind<bool>("Auto Pins", "Pin " + kind, true, "Pin " + kind.ToLowerInvariant() + " as you come near them."),
				Names = cfg.Bind<string>("Auto Pins", kind + " Locations", names, "Locations pinned as " + kind.ToLowerInvariant() + ", by the start of the location's internal name, separated by semicolons.")
			};
		}

		public void Tick(float now)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0183: Unknown result type (might be due to invalid IL or missing references)
			//IL_0188: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_019c: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			Minimap instance = Minimap.instance;
			if (_enabled.Value && ServerRules.Allows("AutoPins") && (Object)(object)localPlayer != (Object)null && (Object)(object)instance != (Object)null && KeyInput.Pressed(_doneKey.Value) && !InventoryFeatures.Typing())
			{
				ToggleDone(instance, localPlayer);
			}
			if (!_enabled.Value || !ServerRules.Allows("AutoPins") || (Object)(object)localPlayer == (Object)null || (Object)(object)instance == (Object)null || now < _next)
			{
				return;
			}
			_next = now + 3f;
			Audit();
			if ((Object)(object)localPlayer != (Object)(object)_for)
			{
				_for = localPlayer;
				_done = (localPlayer.m_customData.TryGetValue("alkeari.senealuiunlocker.autopins", out var value) ? (from s in value.Split(new char[1] { '|' })
					where s.Length > 0
					select s).ToHashSet() : new HashSet<string>());
				_dungeonsDone = (localPlayer.m_customData.TryGetValue("alkeari.senealuiunlocker.dungeonsdone", out var value2) ? (from s in value2.Split(new char[1] { '|' })
					where s.Length > 0
					select s).ToHashSet() : new HashSet<string>());
			}
			Retype(instance);
			CrossOutSeneaLDungeons(instance);
			Vector3 position = ((Component)localPlayer).transform.position;
			Dungeons(instance, localPlayer, now);
			if (Locations(instance, position) + Resources(instance, position) > 0)
			{
				localPlayer.m_customData["alkeari.senealuiunlocker.autopins"] = string.Join("|", _done);
			}
		}

		private int Locations(Minimap map, Vector3 at)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Unknown result type (might be due to invalid IL or missing references)
			int num = 0;
			foreach (Location s_allLocation in Location.s_allLocations)
			{
				if (!((Object)(object)s_allLocation == (Object)null) && !(Vector3.Distance(((Component)s_allLocation).transform.position, at) > _radius.Value))
				{
					string prefab = Prefab(((Component)s_allLocation).gameObject);
					Category category = _categories.FirstOrDefault((Category c) => c.On.Value && Starts(prefab, c.Names.Value));
					if ((category == null || !(category.Kind == "Dungeons") || !SeneaLMarksDungeons()) && category != null)
					{
						num += (Pin(map, ((Component)s_allLocation).transform.position, category.Icon, Label(s_allLocation, prefab), category.Kind) ? 1 : 0);
					}
				}
			}
			return num;
		}

		private int Resources(Minimap map, Vector3 at)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			if (!_resources.Value)
			{
				return 0;
			}
			HashSet<string> hashSet = Split(_resourceItems.Value).ToHashSet<string>(StringComparer.OrdinalIgnoreCase);
			int num = 0;
			foreach (Pickable item in SceneObjects.Live<Pickable>(SceneObjects.Pickables))
			{
				if (!((Object)(object)item == (Object)null) && !((Object)(object)item.m_itemPrefab == (Object)null) && hashSet.Contains(((Object)item.m_itemPrefab).name) && !(Vector3.Distance(((Component)item).transform.position, at) > _radius.Value))
				{
					ItemDrop component = item.m_itemPrefab.GetComponent<ItemDrop>();
					string name = (((Object)(object)component == (Object)null) ? ((Object)item.m_itemPrefab).name : Localization.instance.Localize(component.m_itemData.m_shared.m_name));
					num += (Pin(map, ((Component)item).transform.position, PinKinds.Of("Resources"), name, "res:" + ((Object)item.m_itemPrefab).name, _resourceCluster.Value) ? 1 : 0);
				}
			}
			return num;
		}

		private void Retype(Minimap map)
		{
			//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_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Invalid comparison between Unknown and I4
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: 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_00ce: Invalid comparison between Unknown and I4
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			if (map.m_pins.Count == _retypedAt)
			{
				return;
			}
			_retypedAt = map.m_pins.Count;
			foreach (PinData item in map.m_pins.Where((PinData pin) => (int)pin.m_type == 3 && pin.m_ownerID == 0))
			{
				foreach (string item2 in _done)
				{
					int num = item2.LastIndexOf('@');
					string text = ((num < 0) ? "" : item2.Substring(0, num));
					PinType val = (PinType)((!text.StartsWith("res:", StringComparison.Ordinal)) ? ((!PinKinds.Has(text)) ? 3 : ((int)PinKinds.Of(text))) : ((int)PinKinds.Of("Resources")));
					if ((int)val != 3 && Near(item2, text, item.m_pos, text.StartsWith("res:", StringComparison.Ordinal) ? _resourceCluster.Value : 20f))
					{
						item.m_type = val;
						break;
					}
				}
			}
		}

		private bool Pin(Minimap map, Vector3 pos, PinType icon, string name, string kind, float spread = 20f)
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Invalid comparison between Unknown and I4
			//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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			if (_done.Any((string key) => Near(key, kind, pos, spread)))
			{
				return false;
			}
			_done.Add($"{kind}@{Mathf.RoundToInt(pos.x)},{Mathf.RoundToInt(pos.z)}");
			PinData val = ((IEnumerable<PinData>)map.m_pins).FirstOrDefault((Func<PinData, bool>)((PinData pin) => SameName(pin.m_name, name) && Vector3.Distance(pin.m_pos, pos) < spread));
			if (val == null)
			{
				map.AddPin(pos, icon, name, true, false, 0L, default(PlatformUserID));
			}
			else if ((int)val.m_type == 3)
			{
				val.m_type = icon;
			}
			return true;
		}

		private static bool Near(string key, string kind, Vector3 pos, float spread)
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0062: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006e: Unknown result type (might be due to invalid IL or missing references)
			int num = key.LastIndexOf('@');
			if (num < 0 || key.Substring(0, num) != kind)
			{
				return false;
			}
			string[] array = key.Substring(num + 1).Split(new char[1] { ',' });
			if (array.Length == 2 && int.TryParse(array[0], out var result) && int.TryParse(array[1], out var result2))
			{
				Vector2 val = new Vector2((float)result - pos.x, (float)result2 - pos.z);
				return ((Vector2)(ref val)).magnitude < spread;
			}
			return false;
		}

		private Location CurrentDungeon(Vector3 at)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			Category dungeons = _categories.First((Category c) => c.Kind == "Dungeons");
			return (from l in Location.s_allLocations
				where (Object)(object)l != (Object)null && Starts(Prefab(((Component)l).gameObject), dungeons.Names.Value)
				select (Location: l, Distance: Flat(((Component)l).transform.position, at)) into pair
				where pair.Distance <= Mathf.Max(new float[3]
				{
					pair.Location.m_exteriorRadius,
					pair.Location.m_interiorRadius,
					30f
				})
				orderby pair.Distance
				select pair.Location).FirstOrDefault();
		}

		private PinData DungeonPin(Minimap map, Location dungeon)
		{
			string label = Label(dungeon, Prefab(((Component)dungeon).gameObject));
			PinType? seneaL = SeneaLDungeonPinType();
			return ((IEnumerable<PinData>)map.m_pins).FirstOrDefault((Func<PinData, bool>)((PinData pin) => SameName(pin.m_name, label) && Flat(pin.m_pos, ((Component)dungeon).transform.position) < 20f)) ?? ((IEnumerable<PinData>)map.m_pins).FirstOrDefault((Func<PinData, bool>)((PinData pin) => seneaL.HasValue && pin.m_type == seneaL.Value && Flat(pin.m_pos, ((Component)dungeon).transform.position) < 20f));
		}

		private static PinType? SeneaLDungeonPinType()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			object obj = SeneaLDungeonType?.GetValue(null);
			if (!(obj is PinType))
			{
				return null;
			}
			return (PinType)obj;
		}

		private static bool SeneaLMarksDungeons()
		{
			try
			{
				int result;
				if (SeneaLDungeonType != null && OreWanted != null && OreDetect?.GetValue(null, null) is ConfigEntry<bool> val && val.Value)
				{
					object obj = CanOreDetect?.GetValue(null, null);
					if (obj is bool && (bool)obj)
					{
						obj = OreWanted.Invoke(null, new object[1] { "dungeon" });
						result = ((obj is bool && (bool)obj) ? 1 : 0);
						goto IL_0093;
					}
				}
				result = 0;
				goto IL_0093;
				IL_0093:
				return (byte)result != 0;
			}
			catch (Exception)
			{
				return false;
			}
		}

		private static string DoneSpot(Vector3 pos)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			return $"{Mathf.RoundToInt(pos.x)},{Mathf.RoundToInt(pos.z)}";
		}

		private void SetDone(Player player, PinData pin, bool done)
		{
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			pin.m_checked = done;
			if (!pin.m_save)
			{
				_dungeonsDone.RemoveWhere((string spot) => SameSpot(spot, pin.m_pos));
				if (done)
				{
					_dungeonsDone.Add(DoneSpot(pin.m_pos));
				}
				player.m_customData["alkeari.senealuiunlocker.dungeonsdone"] = string.Join("|", _dungeonsDone);
			}
		}

		private static bool SameSpot(string spot, Vector3 pos)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			string[] array = spot.Split(new char[1] { ',' });
			if (array.Length == 2 && int.TryParse(array[0], out var result) && int.TryParse(array[1], out var result2))
			{
				Vector2 val = new Vector2((float)result - pos.x, (float)result2 - pos.z);
				return ((Vector2)(ref val)).magnitude < 20f;
			}
			return false;
		}

		private void CrossOutSeneaLDungeons(Minimap map)
		{
			PinType? seneaL = SeneaLDungeonPinType();
			if (!seneaL.HasValue || _dungeonsDone.Count == 0)
			{
				return;
			}
			foreach (PinData item in map.m_pins.Where((PinData pin) => pin.m_type == seneaL.Value && !pin.m_checked && _dungeonsDone.Any((string spot) => SameSpot(spot, pin.m_pos))))
			{
				item.m_checked = true;
			}
		}

		private void ToggleDone(Minimap map, Player player)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			Location val = CurrentDungeon(((Component)player).transform.position);
			PinData val2 = (((Object)(object)val == (Object)null) ? null : DungeonPin(map, val));
			if (val2 == null)
			{
				((Character)player).Message((MessageType)1, Lang.T("AutoPins.StandInOrAtA", "Stand in or at a pinned dungeon to mark it done"), 0, (Sprite)null, false);
				return;
			}
			SetDone(player, val2, !val2.m_checked);
			((Character)player).Message((MessageType)1, val2.m_checked ? Lang.F("AutoPins.MarkedDone", "{0} marked done", val2.m_name) : Lang.F("AutoPins.MarkedNotDone", "{0} marked not done", val2.m_name), 0, (Sprite)null, false);
		}

		private void Dungeons(Minimap map, Player player, float now)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			Vector3 position = ((Component)player).transform.position;
			if (_dungeonDone.Value == DungeonDone.Key_Pressed || position.y < 3000f)
			{
				_insideSince = -1f;
				return;
			}
			if (_insideSince < 0f)
			{
				_insideSince = now;
			}
			Location dungeon = CurrentDungeon(position);
			PinData val = (((Object)(object)dungeon == (Object)null) ? null : DungeonPin(map, dungeon));
			float radius;
			if (val != null && !val.m_checked && !(now - _insideSince < 10f))
			{
				radius = Mathf.Max(dungeon.m_interiorRadius, 64f);
				bool flag = (from c in SceneObjects.Live<Container>(SceneObjects.Containers)
					where (Object)(object)c != (Object)null && Inside(((Component)c).transform.position) && c.GetInventory() != null
					select c).All((Container c) => c.GetInventory().NrOfItems() == 0);
				bool flag2 = !Character.GetAllCharacters().Any((Character c) => (Object)(object)c != (Object)null && !c.IsDead() && !c.IsPlayer() && !c.IsTamed() && Inside(((Component)c).transform.position) && BaseAI.IsEnemy((Character)(object)player, c));
				if (_dungeonDone.Value switch
				{
					DungeonDone.All_Chests_Opened => flag, 
					DungeonDone.Enemies_Cleared => flag2, 
					_ => flag && flag2, 
				})
				{
					SetDone(player, val, done: true);
					((Character)player).Message((MessageType)1, Lang.F("AutoPins.MarkedDone", "{0} marked done", val.m_name), 0, (Sprite)null, false);
				}
			}
			bool Inside(Vector3 p)
			{
				//IL_0000: 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_0019: Unknown result type (might be due to invalid IL or missing references)
				if (p.y > 3000f)
				{
					return Flat(p, ((Component)dungeon).transform.position) <= radius;
				}
				return false;
			}
		}

		private static float Flat(Vector3 a, Vector3 b)
		{
			//IL_0000: 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_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			Vector2 val = new Vector2(a.x - b.x, a.z - b.z);
			return ((Vector2)(ref val)).magnitude;
		}

		private static string Label(Location location, string prefab)
		{
			string text = (string.IsNullOrEmpty(location.m_discoverLabel) ? "" : Localization.instance.Localize(location.m_discoverLabel));
			if (text.Length <= 0 || text.StartsWith("["))
			{
				return Readable(prefab);
			}
			return text;
		}

		internal static bool SameName(string pinName, string name)
		{
			if (!(pinName == name))
			{
				return KnownNames.Any(((string Prefix, string Name, string English) pair) => pair.Name == name && pair.English == pinName);
			}
			return true;
		}

		internal static string Readable(string prefab)
		{
			(string, string, string) tuple = KnownNames.FirstOrDefault(((string Prefix, string Name, string English) pair) => prefab.StartsWith(pair.Prefix, StringComparison.OrdinalIgnoreCase));
			if (tuple.Item2 != null)
			{
				return tuple.Item2;
			}
			string text = Regex.Replace(prefab.TrimEnd('0', '1', '2', '3', '4', '5', '6', '7', '8', '9').Replace('_', ' '), "(?<=[a-z])(?=[A-Z])", " ");
			return string.Join(" ", from word in text.Split(new char[1] { ' ' }, StringSplitOptions.RemoveEmptyEntries)
				select char.ToUpperInvariant(word[0]) + word.Substring(1));
		}

		private void Audit()
		{
			ZoneSystem instance = ZoneSystem.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance == (Object)(object)_audited || instance.m_locations == null || instance.m_locations.Count == 0)
			{
				return;
			}
			_audited = instance;
			List<string> known = (from l in instance.m_locations
				where l != null && !string.IsNullOrEmpty(l.m_prefabName)
				select l.m_prefabName).Distinct().ToList();
			Category[] categories = _categories;
			foreach (Category category in categories)
			{
				List<string> list = (from name in Split(category.Names.Value)
					where !known.Any((string k) => k.StartsWith(name, StringComparison.OrdinalIgnoreCase))
					select name).ToList();
				if (list.Count > 0)
				{
					_log.LogInfo((object)("Auto pins: " + category.Kind + " Locations names no location of this world: " + string.Join(", ", list) + "."));
				}
			}
			List<string> list2 = known.Where((string k) => !_categories.Any((Category c) => Starts(k, c.Names.Value))).OrderBy<string, string>((string k) => k, StringComparer.OrdinalIgnoreCase).ToList();
			_log.LogInfo((object)string.Format("Auto pins: locations no category pins ({0}): {1}.", list2.Count, string.Join(", ", list2)));
			List<string> list3 = (from name in Split(_resourceItems.Value)
				where (Object)(object)ObjectDB.instance != (Object)null && (Object)(object)ObjectDB.instance.GetItemPrefab(name) == (Object)null
				select name).ToList();
			if (list3.Count > 0)
			{
				_log.LogInfo((object)("Auto pins: Resource Items names no item: " + string.Join(", ", list3) + "."));
			}
		}

		private static string Prefab(GameObject go)
		{
			string name = ((Object)go).name;
			int num = name.IndexOf("(Clone)", StringComparison.Ordinal);
			return ((num >= 0) ? name.Substring(0, num) : name).Trim();
		}

		private static bool Starts(string prefab, string names)
		{
			return Split(names).Any((string n) => prefab.StartsWith(n, StringComparison.OrdinalIgnoreCase));
		}

		private static IEnumerable<string> Split(string text)
		{
			return from s in text.Split(new char[1] { ';' })
				select s.Trim() into s
				where s.Length > 0
				select s;
		}
	}
	internal enum ShieldChoice
	{
		LastUsed,
		BestBlock,
		BestParry,
		LeastSlowdown
	}
	internal static class AutoShield
	{
		[HarmonyPatch(typeof(Humanoid), "EquipItem")]
		internal static class EquipPatch
		{
			private static void Postfix(Humanoid __instance, ItemData item, bool triggerEquipEffects, bool __result)
			{
				//IL_001a: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0022: Invalid comparison between Unknown and I4
				//IL_0066: Unknown result type (might be due to invalid IL or missing references)
				//IL_0068: Invalid comparison between Unknown and I4
				if (!__result || (Object)(object)__instance != (Object)(object)Player.m_localPlayer || item == null)
				{
					return;
				}
				ItemType itemType = item.m_shared.m_itemType;
				if ((int)itemType == 5)
				{
					_last = item;
					_lastIdentity = Identity(item);
					if (item == _ours)
					{
						_ours = null;
					}
					else if (ServerRules.On(_enabled, "AutoShield"))
					{
						Remember(Player.m_localPlayer, Identity(item));
					}
				}
				else if ((int)itemType == 3 && triggerEquipEffects && item != _hiddenRight && ServerRules.On(_enabled, "AutoShield"))
				{
					_pending = item;
				}
			}
		}

		[HarmonyPatch(typeof(Player), "ToggleEquipped")]
		internal static class TogglePatch
		{
			private static void Prefix(Player __instance, ItemData item)
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001c: Invalid comparison between Unknown and I4
				if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && item != null && (int)item.m_shared.m_itemType == 5 && ((Humanoid)__instance).IsItemEquiped(item) && !((Character)__instance).InAttack())
				{
					_removedAt = Time.time;
					_pending = null;
					Log(item.m_shared.m_name + " taken off by hand");
					if (ServerRules.On(_enabled, "AutoShield"))
					{
						Remember(__instance, "none");
					}
				}
			}
		}

		private static ConfigEntry<bool> _enabled;

		private static ConfigEntry<ShieldChoice> _choice;

		private static ConfigEntry<float> _pause;

		private static ConfigEntry<bool> _pairs;

		private static ConfigEntry<bool> _learn;

		private static ConfigEntry<KeyboardShortcut> _pairKey;

		private static ConfigEntry<bool> _swords;

		private static ConfigEntry<bool> _maces;

		private static ConfigEntry<bool> _axes;

		private static ConfigEntry<bool> _knives;

		private static ConfigEntry<bool> _spears;

		private static ConfigEntry<bool> _others;

		private const string PairKey = "alkeari_shield_pair";

		private const string NoShield = "none";

		private static Player _owner;

		private static ItemData _last;

		private static string _lastIdentity;

		private static ItemData _pending;

		private static ItemData _queued;

		private static ItemData _ours;

		private static ItemData _hiddenRight;

		private static float _removedAt = float.NegativeInfinity;

		public static void Bind(ConfigFile cfg)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Expected O, but got Unknown
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			_enabled = cfg.Bind<bool>("Inventory", "Auto Shield", true, "When you equip a one-handed weapon with nothing in your left hand, a shield from your inventory is equipped with it.");
			_choice = cfg.Bind<ShieldChoice>("Inventory", "Auto Shield Choice", ShieldChoice.LastUsed, "Which shield Auto Shield equips: Last Used (the one you last had equipped this session, else the best blocker), Best Block (highest block power at its quality), Best Parry (block power times parry bonus) or Least Slowdown (smallest movement penalty).");
			_pause = cfg.Bind<float>("Inventory", "Auto Shield Pause Seconds", 10f, new ConfigDescription("After you take a shield off yourself, Auto Shield leaves your left hand empty for this many seconds.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 120f), Array.Empty<object>()));
			_pairs = cfg.Bind<bool>("Inventory", "Shield Pairs", true, "Each one-handed weapon can be paired with a shield, or with no shield: taking that weapon up brings its shield, swaps to it, or puts the shield away. A weapon without a pair follows the Shield With switches and Auto Shield Choice.");
			_learn = cfg.Bind<bool>("Inventory", "Learn Shield Pairs", true, "Putting a shield on or taking it off by hand while holding a one-handed weapon pairs that weapon with that shield, or with no shield. Off = pairs change only with Shield Pair Key.");
			_pairKey = cfg.Bind<KeyboardShortcut>("Inventory", "Shield Pair Key", new KeyboardShortcut((KeyCode)278, Array.Empty<KeyCode>()), "Pairs the one-handed weapon in your hand with the shield you wear, or with no shield when you wear none; pressed again on the same pair, it clears it.");
			_swords = cfg.Bind<bool>("Inventory", "Shield With Swords", true, "Unpaired swords get a shield from Auto Shield. Off = a sword puts the shield away.");
			_maces = cfg.Bind<bool>("Inventory", "Shield With Maces", true, "Unpaired maces and clubs get a shield from Auto Shield. Off = they put the shield away.");
			_axes = cfg.Bind<bool>("Inventory", "Shield With Axes", false, "Unpaired one-handed axes get a shield from Auto Shield. Off by default since axes are also the woodcutting tool; off = an axe puts the shield away.");
			_knives = cfg.Bind<bool>("Inventory", "Shield With Knives", true, "Unpaired knives get a shield from Auto Shield. Off = a knife puts the shield away.");
			_spears = cfg.Bind<bool>("Inventory", "Shield With Spears", true, "Unpaired spears get a shield from Auto Shield. Off = a spear puts the shield away.");
			_others = cfg.Bind<bool>("Inventory", "Shield With Other Weapons", true, "Unpaired one-handed weapons of any other kind (magic and modded weapons) get a shield from Auto Shield. Off = they put the shield away.");
		}

		public static void Tick()
		{
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011b: Invalid comparison between Unknown and I4
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer != (Object)(object)_owner)
			{
				_owner = localPlayer;
				_last = null;
				_lastIdentity = null;
				_pending = null;
				_queued = null;
				_removedAt = float.NegativeInfinity;
			}
			if ((Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			_hiddenRight = ((Humanoid)localPlayer).m_hiddenRightItem;
			if (_queued != null && localPlayer.IsEquipActionQueued(_queued) && !HandsWant(localPlayer))
			{
				((Humanoid)localPlayer).RemoveEquipAction(_queued);
				Log("cancelled the queued " + _queued.m_shared.m_name + ": the hands changed");
				_queued = null;
			}
			HandlePairKey(localPlayer);
			if (_pending == null)
			{
				return;
			}
			string text = Pair(_pending) ?? (KindWantsShield(_pending) ? null : "none");
			if (!ServerRules.On(_enabled, "AutoShield") || ((Humanoid)localPlayer).GetRightItem() != _pending || ((Humanoid)localPlayer).m_hiddenLeftItem != null || ShieldQueued(localPlayer) || (((Humanoid)localPlayer).GetLeftItem() != null && (text == null || (int)((Humanoid)localPlayer).GetLeftItem().m_shared.m_itemType != 5)))
			{
				_pending = null;
			}
			else if (text != null)
			{
				if (!((Character)localPlayer).IsDead() && !((Character)localPlayer).InAttack() && !((Character)localPlayer).InDodge() && !((Character)localPlayer).IsSwimming() && !((Character)localPlayer).InCutscene() && !((Character)localPlayer).IsTeleporting() && !localPlayer.IsSleeping() && !((Character)localPlayer).IsAttached())
				{
					_pending = null;
					Paired(localPlayer, text);
				}
			}
			else if (!HandsWant(localPlayer))
			{
				_pending = null;
			}
			else if (Time.time - _removedAt < _pause.Value)
			{
				Log("skipped: a shield was taken off by hand moments ago");
				_pending = null;
			}
			else if (!((Character)localPlayer).IsDead() && !((Character)localPlayer).InAttack() && !((Character)localPlayer).InDodge() && !((Character)localPlayer).IsSwimming() && !((Character)localPlayer).InCutscene() && !((Character)localPlayer).IsTeleporting() && !localPlayer.IsSleeping() && !((Character)localPlayer).IsAttached())
			{
				_pending = null;
				ItemData val = Pick(localPlayer);
				if (val != null)
				{
					_ours = val;
					((Humanoid)localPlayer).ToggleEquipped(val);
					_queued = (localPlayer.IsEquipActionQueued(val) ? val : null);
					Log(string.Format("{0} q{1} {2} with {3} ({4})", val.m_shared.m_name, val.m_quality, (_queued == null) ? "equipped" : "queued", ((Humanoid)localPlayer).GetRightItem().m_shared.m_name, _choice.Value));
				}
			}
		}

		private static string Pair(ItemData weapon)
		{
			if (!_pairs.Value || !weapon.m_customData.TryGetValue("alkeari_shield_pair", out var value) || value.Length <= 0)
			{
				return null;
			}
			return value;
		}

		private static bool KindWantsShield(ItemData weapon)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: Expected I4, but got Unknown
			SkillType skillType = weapon.m_shared.m_skillType;
			return (skillType - 1) switch
			{
				0 => _swords.Value, 
				2 => _maces.Value, 
				6 => _axes.Value, 
				1 => _knives.Value, 
				4 => _spears.Value, 
				_ => _others.Value, 
			};
		}

		private static void HandlePairKey(Player player)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Invalid comparison between Unknown and I4
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Invalid comparison between Unknown and I4
			if (!_pairs.Value || InventoryFeatures.Typing() || !KeyInput.Down(_pairKey.Value) || !ServerRules.On(_enabled, "AutoShield"))
			{
				return;
			}
			ItemData rightItem = ((Humanoid)player).GetRightItem();
			if (rightItem == null || (int)rightItem.m_shared.m_itemType != 3)
			{
				((Character)player).Message((MessageType)2, Lang.T("AutoShield.HoldAOneHandedWeapon", "Hold a one-handed weapon to pair it with a shield"), 0, (Sprite)null, false);
				return;
			}
			ItemData leftItem = ((Humanoid)player).GetLeftItem();
			string text = ((leftItem != null && (int)leftItem.m_shared.m_itemType == 5) ? Identity(leftItem) : "none");
			string text2 = Localization.instance.Localize(rightItem.m_shared.m_name);
			if (rightItem.m_customData.TryGetValue("alkeari_shield_pair", out var value) && value == text)
			{
				rightItem.m_customData.Remove("alkeari_shield_pair");
				((Character)player).Message((MessageType)1, Lang.F("AutoShield.UnpairedItFollowsTheShield", "{0} unpaired: it follows the Shield With settings", text2), 0, (Sprite)null, false);
				Log(rightItem.m_shared.m_name + " unpaired by key");
			}
			else
			{
				rightItem.m_customData["alkeari_shield_pair"] = text;
				((Character)player).Message((MessageType)1, (text == "none") ? Lang.F("AutoShield.PairedWithNoShield", "{0} paired with no shield", text2) : Lang.F("AutoShield.PairedWith", "{0} paired with {1}", text2, Localization.instance.Localize(leftItem.m_shared.m_name)), 0, (Sprite)null, false);
				Log(rightItem.m_shared.m_name + " paired with " + ((text == "none") ? "no shield" : text) + " by key");
			}
		}

		private static void Paired(Player player, string pair)
		{
			ItemData leftItem = ((Humanoid)player).GetLeftItem();
			string name = ((Humanoid)player).GetRightItem().m_shared.m_name;
			if (pair == "none")
			{
				if (leftItem != null)
				{
					((Humanoid)player).UnequipItem(leftItem, true);
					Log(leftItem.m_shared.m_name + " put away: " + name + " is paired with no shield");
				}
			}
			else
			{
				if (leftItem != null && Identity(leftItem) == pair)
				{
					return;
				}
				ItemData val = (from item in ((Humanoid)player).GetInventory().GetAllItems()
					where Usable(item) && Identity(item) == pair
					orderby item.m_durability descending
					select item).FirstOrDefault();
				if (val == null)
				{
					val = ((leftItem == null) ? Pick(player) : null);
					if (val == null)
					{
						return;
					}
				}
				_ours = val;
				((Humanoid)player).ToggleEquipped(val);
				_queued = (player.IsEquipActionQueued(val) ? val : null);
				Log(string.Format("{0} q{1} {2} with {3} (pair {4})", val.m_shared.m_name, val.m_quality, (_queued == null) ? "equipped" : "queued", name, pair));
			}
		}

		private static void Remember(Player player, string pair)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Invalid comparison between Unknown and I4
			ItemData rightItem = ((Humanoid)player).GetRightItem();
			if (_pairs.Value && _learn.Value && rightItem != null && (int)rightItem.m_shared.m_itemType == 3 && (!rightItem.m_customData.TryGetValue("alkeari_shield_pair", out var value) || value != pair))
			{
				rightItem.m_customData["alkeari_shield_pair"] = pair;
				Log(rightItem.m_shared.m_name + " paired with " + ((pair == "none") ? "no shield" : pair));
			}
		}

		private static bool HandsWant(Player player)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: Invalid comparison between Unknown and I4
			ItemData rightItem = ((Humanoid)player).GetRightItem();
			if (rightItem != null && (int)rightItem.m_shared.m_itemType == 3 && ((Humanoid)player).GetLeftItem() == null)
			{
				return ((Humanoid)player).m_hiddenLeftItem == null;
			}
			return false;
		}

		private static bool ShieldQueued(Player player)
		{
			return player.m_actionQueue.Any((MinorActionData action) => (int)action.m_type == 0 && action.m_item != null && (int)action.m_item.m_shared.m_itemType == 5);
		}

		private static ItemData Pick(Player player)
		{
			List<ItemData> list = ((Humanoid)player).GetInventory().GetAllItems().Where(Usable)
				.ToList();
			if (list.Count == 0)
			{
				return null;
			}
			switch (_choice.Value)
			{
			case ShieldChoice.LastUsed:
				if (_last != null && list.Contains(_last))
				{
					return _last;
				}
				return (from item in list
					where Identity(item) == _lastIdentity
					orderby item.m_durability descending
					select item).FirstOrDefault() ?? list.OrderByDescending(Block).ThenByDescending((ItemData item) => item.m_durability).First();
			case ShieldChoice.BestParry:
				return list.OrderByDescending((ItemData item) => Block(item) * item.m_shared.m_timedBlockBonus).ThenByDescending(Block).First();
			case ShieldChoice.LeastSlowdown:
				return list.OrderByDescending((ItemData item) => item.m_shared.m_movementModifier).ThenByDescending(Block).First();
			default:
				return list.OrderByDescending(Block).ThenByDescending((ItemData item) => item.m_durability).First();
			}
		}

		private static bool Usable(ItemData item)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Invalid comparison between Unknown and I4
			if ((int)item.m_shared.m_itemType == 5 && item.IsEquipable() && (!item.m_shared.m_useDurability || !(item.m_durability <= 0f)))
			{
				if (item.m_shared.m_dlc.Length != 0)
				{
					if ((Object)(object)DLCMan.instance != (Object)null)
					{
						return DLCMan.instance.IsDLCInstalled(item.m_shared.m_dlc);
					}
					return false;
				}
				return true;
			}
			return false;
		}

		private static float Block(ItemData item)
		{
			return item.GetBaseBlockPower(item.m_quality);
		}

		private static string Identity(ItemData item)
		{
			return $"{item.m_shared.m_name}|{item.m_quality}|{item.m_variant}";
		}

		private static void Log(string message)
		{
			if (DebugLog.On)
			{
				DebugLog.Write("auto shield", message);
			}
		}
	}
	internal static class BadgersShadingCompat
	{
		internal const string BadgersShadingGuid = "Badgers.ShadingOverhaul";

		private static ConfigEntry<bool> _enabled;

		public static void Resolve(ConfigFile cfg, Harmony harmony, ManualLogSource log)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			if (Chainloader.PluginInfos.TryGetValue("Badgers.ShadingOverhaul", out var value) && !((Object)(object)value.Instance == (Object)null))
			{
				MethodInfo methodInfo = AccessTools.Method(((object)value.Instance).GetType(), "Update", (Type[])null, (Type[])null);
				if (methodInfo == null)
				{
					log.LogWarning((object)"Badgers Shading Overhaul has an unknown shape; Chest Keys Skip Badgers Shading Menu is off.");
					return;
				}
				_enabled = cfg.Bind<bool>("Compatibility", "Chest Keys Skip Badgers Shading Menu", true, "With Badgers Shading Overhaul, Next Chest Key and Previous Chest Key with a chest open do not also open its shading menu when it uses the same key.");
				harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(AccessTools.Method(typeof(BadgersShadingCompat), "BeforeUpdate", (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
			}
		}

		private static bool BeforeUpdate()
		{
			if (_enabled.Value)
			{
				return !CycleChests.ChestKeyDown;
			}
			return true;
		}
	}
	internal sealed class BedAndHotbar
	{
		private readonly ConfigEntry<bool> _bedPins;

		private readonly ConfigEntry<PinType> _bedIcon;

		private readonly ConfigEntry<bool> _swap;

		private readonly ConfigEntry<KeyboardShortcut> _swapKey;

		private readonly ConfigEntry<int> _swapRow;

		private Vector3? _bed;

		private float _next;

		public BedAndHotbar(ConfigFile cfg)
		{
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a9: Expected O, but got Unknown
			_bedPins = cfg.Bind<bool>("Map", "Keep Old Bed Pins", true, "When you set your spawn point at a new bed, a saved pin named Old Bed stays where the previous bed was.");
			_bedIcon = cfg.Bind<PinType>("Map", "Old Bed Pin Icon", (PinType)1, "The map icon of the pin Keep Old Bed Pins leaves at an old bed.");
			_swap = cfg.Bind<bool>("Inventory", "Hotbar Swap", true, "Hotbar Swap Key trades the items of the hotbar with those of Hotbar Swap Row, keeping what you wear equipped.");
			_swapKey = cfg.Bind<KeyboardShortcut>("Inventory", "Hotbar Swap Key", new KeyboardShortcut((KeyCode)106, Array.Empty<KeyCode>()), "Trades the hotbar with Hotbar Swap Row, while Hotbar Swap is on.");
			_swapRow = cfg.Bind<int>("Inventory", "Hotbar Swap Row", 2, new ConfigDescription("The inventory row, counted from the hotbar as row 1, that Hotbar Swap Key trades with the hotbar.", (AcceptableValueBase)(object)new AcceptableValueRange<int>(2, 8), Array.Empty<object>()));
		}

		public void Tick(float now)
		{
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_013c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				_bed = null;
				return;
			}
			Swap(localPlayer);
			if (now < _next)
			{
				return;
			}
			_next = now + 2f;
			PlayerProfile val = (((Object)(object)Game.instance == (Object)null) ? null : Game.instance.GetPlayerProfile());
			if (val == null || !val.HaveCustomSpawnPoint())
			{
				return;
			}
			Vector3 customSpawnPoint = val.GetCustomSpawnPoint();
			Vector3? bed = _bed;
			if (bed.HasValue)
			{
				Vector3 old = bed.GetValueOrDefault();
				if (Vector3.Distance(old, customSpawnPoint) > 5f && _bedPins.Value && ServerRules.Allows("OldBedPins") && (Object)(object)Minimap.instance != (Object)null && Minimap.instance.m_pins.TrueForAll((PinData pin) => (pin.m_name != "Old Bed" && pin.m_name != Lang.T("BedAndHotbar.OldBed", "Old Bed")) || Vector3.Distance(pin.m_pos, old) > 5f))
				{
					Minimap.instance.AddPin(old, _bedIcon.Value, Lang.T("BedAndHotbar.OldBed", "Old Bed"), true, false, 0L, default(PlatformUserID));
					if (DebugLog.On)
					{
						DebugLog.Write("pins", $"old bed pin at {old}, new bed at {customSpawnPoint}");
					}
				}
			}
			_bed = customSpawnPoint;
		}

		private void Swap(Player player)
		{
			//IL_001a: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			if (!_swap.Value || InventoryFeatures.Typing() || !KeyInput.Down(_swapKey.Value) || !ServerRules.Allows("HotbarSwap"))
			{
				return;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			int num = _swapRow.Value - 1;
			if (num >= (SeneaLCalls.CanSort ? SeneaLCalls.MainRows(inventory) : inventory.GetHeight()))
			{
				((Character)player).Message((MessageType)2, Lang.F("BedAndHotbar.YourInventoryHasNoRow", "Your inventory has no row {0}", _swapRow.Value), 0, (Sprite)null, false);
				return;
			}
			for (int i = 0; i < inventory.GetWidth(); i++)
			{
				ItemData itemAt = inventory.GetItemAt(i, 0);
				ItemData itemAt2 = inventory.GetItemAt(i, num);
				if (itemAt != null)
				{
					itemAt.m_gridPos = new Vector2i(i, num);
				}
				if (itemAt2 != null)
				{
					itemAt2.m_gridPos = new Vector2i(i, 0);
				}
			}
			inventory.Changed(false, false);
			if (DebugLog.On)
			{
				DebugLog.Write("hotbar", $"swapped the hotbar with row {_swapRow.Value}");
			}
		}
	}
	internal sealed class BeyondMaximums
	{
		private sealed record Lift(float Max, ConfigEntry<float> Cap, Func<float> Reach);

		private const string Section = "Cheats: Beyond Maximums";

		private const string PatchId = "alkeari.valheim.senealuiunlocker.beyond";

		private const string GuardId = "alkeari.valheim.senealuiunlocker.beyond.guard";

		private const string PolicyType = "SeneaLUI.Net.Policy";

		private const string PovType = "SeneaLUI.Mods.Pov";

		private const string BlipsType = "SeneaLUI.Radar.Blips";

		private const string PolicyRpcName = "SeneaLUI_Policy";

		private static readonly int PolicyRpc = StringExtensionMethods.GetStableHashCode("SeneaLUI_Policy");

		private static BeyondMaximums _current;

		private readonly ManualLogSource _log;

		private readonly PolicyUnlock _unlock;

		private readonly ConfigEntry<bool> _on;

		private readonly Harmony _patches = new Harmony("alkeari.valheim.senealuiunlocker.beyond");

		private readonly Harmony _guard = new Harmony("alkeari.valheim.senealuiunlocker.beyond.guard");

		private readonly Lift[] _lifts;

		private readonly (MethodInfo Getter, string Postfix)[] _targets;

		private bool _eligible;

		private bool _applied;

		private bool _guardApplied;

		private bool _broken;

		private bool Live
		{
			get
			{
				if (_applied)
				{
					if (!_unlock.IsUnlocked)
					{
						return _unlock.OwnWorld;
					}
					return true;
				}
				return false;
			}
		}

		private BeyondMaximums(ManualLogSource log, PolicyUnlock unlock, ConfigEntry<bool> on, Lift[] lifts, (MethodInfo, string)[] targets)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Expected O, but got Unknown
			_log = log;
			_unlock = unlock;
			_on = on;
			_lifts = lifts;
			_targets = targets;
		}

		public static BeyondMaximums Resolve(ConfigFile cfg, ManualLogSource log, PolicyUnlock unlock)
		{
			ConfigEntry<bool> val = cfg.Bind<bool>("Cheats: Beyond Maximums", "Go Beyond SeneaL UI Maximums (Cheat)", false, "Cheat, off by default: in your own world and on servers without SeneaL UI, raise the ranges below past SeneaL UI's own maximums. It patches SeneaL UI's code there; the patches are removed before a SeneaL UI server could see them.");
			ConfigEntry<float> cap = Cap(cfg, "Max Chest Range Beyond", 200f, 100f, 500f, "Chest range, meters, for crafting, building, quick stack and restock wherever SeneaL UI's own range is at its 100 m maximum. Chests farther away than the game has loaded are not found.");
			ConfigEntry<float> cap2 = Cap(cfg, "Max Area Pickup Beyond", 20f, 10f, 50f, "Area pickup radius, meters, used when SeneaL UI's own radius is at its 10 m maximum.");
			ConfigEntry<float> cap3 = Cap(cfg, "Max Ore Radius Beyond", 120f, 60f, 300f, "Ore detection radius, meters, used when SeneaL UI's own radius is at its 60 m maximum.");
			ConfigEntry<float> cap4 = Cap(cfg, "Max Radar Range Beyond", 300f, 200f, 500f, "SeneaL Radar range, meters, used when the radar's own range is at its 200 m maximum.");
			Type type = TypeLookup.Find("SeneaLUI.Net.Policy");
			if (unlock == null || type == null)
			{
				return null;
			}
			Type pov = TypeLookup.Find("SeneaLUI.Mods.Pov");
			Func<float> reach = Reach(pov, "ChestReach");
			Func<float> reach2 = Reach(pov, "PickupReach");
			float max = Constant(type, "MaxRange");
			float max2 = Constant(type, "MaxArea");
			float max3 = Constant(type, "MaxOre");
			float max4 = Constant(type, "MaxRadar");
			Lift[] lifts = new Lift[6]
			{
				new Lift(max, cap, reach),
				new Lift(max, cap, reach),
				new Lift(max, cap, null),
				new Lift(max2, cap2, reach2),
				new Lift(max3, cap3, null),
				new Lift(max4, cap4, null)
			};
			Type type2 = Quiet.Type("SeneaLUI.Radar.Blips");
			(MethodInfo, string)[] array = new(MethodInfo, string)[6]
			{
				(Getter(type, "ChestRange", max), "ChestRange"),
				(Getter(type, "BuildRange", max), "BuildRange"),
				(Getter(type, "StackRange", max), "StackRange"),
				(Getter(type, "AreaRange", max2), "AreaRange"),
				(Getter(type, "OreRadius", max3), "OreRadius"),
				((type2 == null) ? null : Getter(type2, "Range", max4), "RadarRange")
			};
			if (Array.TrueForAll(array, ((MethodInfo, string) t) => t.Item1 == null))
			{
				log.LogWarning((object)"This SeneaL UI build has none of the ranges Go Beyond SeneaL UI Maximums (Cheat) raises, so it does nothing.");
				return null;
			}
			BeyondMaximums beyond = new BeyondMaximums(log, unlock, val, lifts, array);
			_current = beyond;
			unlock.Granted += delegate
			{
				beyond.Granted();
			};
			return beyond;
		}

		private static ConfigEntry<float> Cap(ConfigFile cfg, string key, float value, float min, float max, string desc)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Expected O, but got Unknown
			return cfg.Bind<float>("Cheats: Beyond Maximums", key, value, new ConfigDescription(desc, (AcceptableValueBase)(object)new AcceptableValueRange<float>(min, max), Array.Empty<object>()));
		}

		private static Func<float> Reach(Type pov, string name)
		{
			MethodInfo methodInfo = ((pov == null) ? null : AccessTools.PropertyGetter(pov, name));
			if (!(methodInfo == null))
			{
				return AccessTools.MethodDelegate<Func<float>>(methodInfo, (object)null, true);
			}
			return null;
		}

		private static float Constant(Type type, string name)
		{
			object obj = AccessTools.Field(type, name)?.GetValue(null);
			if (obj is float)
			{
				return (float)obj;
			}
			return float.NaN;
		}

		private static MethodInfo Getter(Type type, string name, float max)
		{
			if (!float.IsNaN(max))
			{
				return AccessTools.PropertyGetter(type, name);
			}
			return null;
		}

		private void Granted()
		{
			_eligible = true;
			Tick();
		}

		public void Tick()
		{
			if (_guardApplied && !_applied)
			{
				_guard.UnpatchSelf();
				_guardApplied = false;
			}
			if (_unlock.OwnWorld)
			{
				_eligible = true;
			}
			else if (!_unlock.IsUnlocked)
			{
				_eligible = false;
			}
			bool flag = _on.Value && ServerRules.Allows("BeyondMaximums") && _eligible && !_broken && ServerDirectory.Option("beyond", fallback: true);
			if (flag && !_applied)
			{
				Apply();
			}
			else if (!flag && _applied)
			{
				Remove("the unlock or the setting ended");
			}
		}

		public void Shutdown()
		{
			_patches.UnpatchSelf();
			_guard.UnpatchSelf();
			_applied = false;
			_guardApplied = false;
		}

		private void Apply()
		{
			//IL_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Expected O, but got Unknown
			try
			{
				if (!_guardApplied)
				{
					_guard.Patch((MethodBase)AccessTools.Method(typeof(ZRpc), "HandlePackage", (Type[])null, (Type[])null), Guard("BeforePackage"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					_guard.Patch((MethodBase)AccessTools.Method(typeof(ZNet), "StopAll", (Type[])null, (Type[])null), Guard("BeforeConnectionChange"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					_guard.Patch((MethodBase)AccessTools.Method(typeof(ZNet), "OnNewConnection", (Type[])null, (Type[])null), Guard("BeforeConnectionChange"), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					_guardApplied = true;
				}
				(MethodInfo, string)[] targets = _targets;
				for (int i = 0; i < targets.Length; i++)
				{
					var (methodInfo, text) = targets[i];
					if (methodInfo != null)
					{
						_patches.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(AccessTools.Method(typeof(BeyondMaximums), text, (Type[])null, (Type[])null)), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					}
				}
				_applied = true;
				_log.LogInfo((object)"SeneaL UI's range maximums are raised on this server.");
			}
			catch (Exception ex)
			{
				_broken = true;
				_patches.UnpatchSelf();
				_applied = false;
				_log.LogWarning((object)("Could not raise SeneaL UI's maximums (" + ex.GetBaseException().Message + "); Go Beyond SeneaL UI Maximums (Cheat) stays off until the game restarts."));
			}
		}

		private static HarmonyMethod Guard(string name)
		{
			//IL_0012: 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_0023: Expected O, but got Unknown
			return new HarmonyMethod(AccessTools.Method(typeof(BeyondMaximums), name, (Type[])null, (Type[])null))
			{
				priority = 800
			};
		}

		private void Remove(string why)
		{
			_patches.UnpatchSelf();
			_applied = false;
			_log.LogInfo((object)("SeneaL UI's range maximums are back (" + why + ")."));
		}

		private static void BeforePackage(ZPackage package)
		{
			BeyondMaximums current = _current;
			if (current == null || !current._applied)
			{
				return;
			}
			int pos = package.GetPos();
			if (package.Size() - pos >= 4)
			{
				int num = package.ReadInt();
				package.SetPos(pos);
				if (num == PolicyRpc)
				{
					current._eligible = false;
					current.Remove("the server runs SeneaL UI");
				}
			}
		}

		private static void BeforeConnectionChange()
		{
			BeyondMaximums current = _current;
			if (current != null)
			{
				current._eligible = false;
				if (current._applied)
				{
					current.Remove("the connection changed");
				}
			}
		}

		private static void ChestRange(ref float __result)
		{
			__result = _current.Raise(0, __result);
		}

		private static void BuildRange(ref float __result)
		{
			__result = _current.Raise(1, __result);
		}

		private static void StackRange(ref float __result)
		{
			__result = _current.Raise(2, __result);
		}

		private static void AreaRange(ref float __result)
		{
			__result = _current.Raise(3, __result);
		}

		private static void OreRadius(ref float __result)
		{
			__result = _current.Raise(4, __result);
		}

		private static void RadarRange(ref float __result)
		{
			__result = _current.Raise(5, __result);
		}

		private float Raise(int index, float value)
		{
			Lift lift = _lifts[index];
			if (!Live || value < lift.Max - 0.01f)
			{
				return value;
			}
			float value2 = lift.Cap.Value;
			if (lift.Reach != null)
			{
				return Mathf.Min(value2, lift.Reach());
			}
			return value2;
		}
	}
	internal static class BuildCamera
	{
		[HarmonyPatch(typeof(GameCamera), "UpdateCamera")]
		internal static class CameraPatch
		{
			private static bool Prefix(GameCamera __instance, float dt)
			{
				//IL_0067: Unknown result type (might be due to invalid IL or missing references)
				//IL_0071: Unknown result type (might be due to invalid IL or missing references)
				//IL_0076: Unknown result type (might be due to invalid IL or missing references)
				//IL_007c: Unknown result type (might be due to invalid IL or missing references)
				//IL_008d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bb: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
				//IL_00dd: 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_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_00f5: 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_0122: Unknown result type (might be due to invalid IL or missing references)
				//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_0127: 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_0102: Unknown result type (might be due to invalid IL or missing references)
				//IL_0103: Unknown result type (might be due to invalid IL or missing references)
				//IL_0108: Unknown result type (might be due to invalid IL or missing references)
				//IL_010d: Unknown result type (might be due to invalid IL or missing references)
				//IL_013a: Unknown result type (might be due to invalid IL or missing references)
				//IL_013c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0141: Unknown result type (might be due to invalid IL or missing references)
				//IL_0146: Unknown result type (might be due to invalid IL or missing references)
				//IL_0154: Unknown result type (might be due to invalid IL or missing references)
				//IL_0156: Unknown result type (might be due to invalid IL or missing references)
				//IL_015b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0160: Unknown result type (might be due to invalid IL or missing references)
				//IL_0188: Unknown result type (might be due to invalid IL or missing references)
				//IL_018d: 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_019b: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a6: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
				//IL_01bc: Unknown result type (might be due to invalid IL or missing references)
				//IL_01fa: Unknown result type (might be due to invalid IL or missing references)
				//IL_0202: Unknown result type (might be due to invalid IL or missing references)
				//IL_01cf: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d1: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01d5: Unknown result type (might be due to invalid IL or missing references)
				//IL_01da: Unknown result type (might be due to invalid IL or missing references)
				//IL_01de: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f2: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f7: Unknown result type (might be due to invalid IL or missing references)
				Player localPlayer = Player.m_localPlayer;
				if (!_active || (Object)(object)localPlayer == (Object)null)
				{
					return true;
				}
				bool num = !Hud.IsPieceSelectionVisible() && !InventoryGui.IsVisible() && !Menu.IsVisible() && !Minimap.IsOpen() && !Console.IsVisible() && ((Object)(object)Chat.instance == (Object)null || !Chat.instance.HasFocus());
				Transform transform = ((Component)__instance).transform;
				if (num)
				{
					Vector2 val = ZInput.GetMouseDelta() * PlayerController.m_mouseSens;
					_yaw += val.x;
					_pitch = Mathf.Clamp(_pitch - val.y, -89f, 89f);
					Vector3 val2 = Vector3.zero;
					if (ZInput.GetButton("Forward"))
					{
						val2 += Vector3.forward;
					}
					if (ZInput.GetButton("Backward"))
					{
						val2 -= Vector3.forward;
					}
					if (ZInput.GetButton("Right"))
					{
						val2 += Vector3.right;
					}
					if (ZInput.GetButton("Left"))
					{
						val2 -= Vector3.right;
					}
					Quaternion val3 = Quaternion.Euler(_pitch, _yaw, 0f);
					Vector3 val4 = val3 * val2;
					if (ZInput.GetButton("Jump"))
					{
						val4 += Vector3.up;
					}
					if (ZInput.GetButton("Crouch"))
					{
						val4 -= Vector3.up;
					}
					float num2 = _speed.Value * (ZInput.GetButton("Run") ? 3f : 1f);
					Vector3 val5 = transform.position + Vector3.ClampMagnitude(val4, 1f) * num2 * dt;
					Vector3 position = ((Character)localPlayer).m_eye.position;
					if (Vector3.Distance(val5, position) > _range.Value)
					{
						Vector3 val6 = val5 - position;
						val5 = position + ((Vector3)(ref val6)).normalized * _range.Value;
					}
					transform.position = val5;
					transform.rotation = val3;
				}
				__instance.m_camera.fieldOfView = __instance.m_fov;
				__instance.m_skyCamera.fieldOfView = __instance.m_fov;
				return false;
			}
		}

		[HarmonyPatch(typeof(Player), "SetControls")]
		internal static class ControlsPatch
		{
			private static void Prefix(Player __instance, ref Vector3 movedir, ref bool jump, ref bool crouch, ref bool run, ref bool autoRun, ref bool dodge)
			{
				//IL_0016: Unknown result type (might be due to invalid IL or missing references)
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				if (_active && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer))
				{
					movedir = Vector3.zero;
					jump = false;
					crouch = false;
					run = false;
					autoRun = false;
					dodge = false;
				}
			}
		}

		private const string Section = "Building";

		private static ConfigEntry<bool> _on;

		private static ConfigEntry<KeyboardShortcut> _key;

		private static ConfigEntry<float> _range;

		private static ConfigEntry<float> _speed;

		private static bool _active;

		private static float _yaw;

		private static float _pitch;

		private static float _health;

		private static float _savedReach = -1f;

		internal static bool Active => _active;

		public static void Bind(ConfigFile cfg)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Expected O, but got Unknown
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Expected O, but got Unknown
			_on = cfg.Bind<bool>("Building", "Build Camera", true, "Build Camera Key lets the camera fly free around your build while a building tool is in hand; placing works from where it looks.");
			_key = cfg.Bind<KeyboardShortcut>("Building", "Build Camera Key", new KeyboardShortcut((KeyCode)111, Array.Empty<KeyCode>()), "Starts and stops the build camera while Build Camera is on and a hammer, hoe or cultivator is in hand.");
			_range = cfg.Bind<float>("Building", "Build Camera Range", 30f, new ConfigDescription("How far from your character, in meters, the build camera may fly, and so how far away you can place pieces with it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(8f, 60f), Array.Empty<object>()));
			_speed = cfg.Bind<float>("Building", "Build Camera Speed", 8f, new ConfigDescription("How fast the build camera flies, meters per second; hold Run for three times as fast.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 30f), Array.Empty<object>()));
		}

		public static void Tick()
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			if (_active && ((Object)(object)localPlayer == (Object)null || ((Character)localPlayer).IsDead() || !((Character)localPlayer).InPlaceMode() || ((Character)localPlayer).GetHealth() < _health - 0.01f || !_on.Value || !ServerRules.Allows("BuildCamera")))
			{
				Stop(localPlayer);
			}
			else if (!((Object)(object)localPlayer == (Object)null) && _on.Value && !InventoryFeatures.Typing() && KeyInput.Down(_key.Value) && ServerRules.Allows("BuildCamera"))
			{
				if (_active)
				{
					Stop(localPlayer);
				}
				else if (((Character)localPlayer).InPlaceMode() && (Object)(object)GameCamera.instance != (Object)null)
				{
					Start(localPlayer);
				}
			}
		}

		private static void Start(Player player)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: 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_0018: 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_0038: 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)
			Quaternion rotation = ((Component)GameCamera.instance).transform.rotation;
			Vector3 eulerAngles = ((Quaternion)(ref rotation)).eulerAngles;
			_yaw = eulerAngles.y;
			_pitch = ((eulerAngles.x > 180f) ? (eulerAngles.x - 360f) : eulerAngles.x);
			_health = ((Character)player).GetHealth();
			_savedReach = player.m_maxPlaceDistance;
			player.m_maxPlaceDistance = Mathf.Max(_savedReach, _range.Value + 10f);
			_active = true;
			((Character)player).Message((MessageType)1, Lang.T("BuildCamera.BuildCameraOn", "Build camera on"), 0, (Sprite)null, false);
			Log("on");
		}

		private static void Stop(Player player)
		{
			_active = false;
			if ((Object)(object)player != (Object)null && _savedReach >= 0f)
			{
				player.m_maxPlaceDistance = _savedReach;
			}
			_savedReach = -1f;
			if ((Object)(object)player != (Object)null)
			{
				((Character)player).Message((MessageType)1, Lang.T("BuildCamera.BuildCameraOff", "Build camera off"), 0, (Sprite)null, false);
			}
			Log("off");
		}

		private static void Log(string what)
		{
			if (DebugLog.On)
			{
				DebugLog.Write("build camera", what);
			}
		}
	}
	internal static class BuildRestrictions
	{
		[HarmonyPatch(typeof(StationExtension), "OtherExtensionInRange")]
		internal static class SpacingPatch
		{
			private static void Postfix(ref bool __result)
			{
				if ((Object)(object)_placing != (Object)null && Mode() != "Vanilla")
				{
					__result = false;
				}
			}
		}

		[HarmonyPatch(typeof(Player), "UpdatePlacementGhost")]
		internal static class GhostPatch
		{
			private static void Prefix(Player __instance)
			{
				_placing = (((Object)(object)__instance == (Object)(object)Player.m_localPlayer) ? __instance : null);
			}

			private static void Postfix(Player __instance)
			{
				//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_0044: Unknown result type (might be due to invalid IL or missing references)
				//IL_0047: Unknown result type (might be due to invalid IL or missing references)
				//IL_004a: Invalid comparison between Unknown and I4
				//IL_004c: Unknown result type (might be due to invalid IL or missing references)
				//IL_004e: Invalid comparison between Unknown and I4
				//IL_0050: Unknown result type (might be due to invalid IL or missing references)
				//IL_0052: Invalid comparison between Unknown and I4
				//IL_008c: 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_0062: Invalid comparison between Unknown and I4
				//IL_00c0: 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)
				_placing = null;
				GameObject placementGhost = __instance.m_placementGhost;
				if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && !((Object)(object)placementGhost == (Object)null) && placementGhost.activeSelf && !(Mode() != "Unrestricted (Cheat)"))
				{
					PlacementStatus placementStatus = __instance.m_placementStatus;
					if ((int)placementStatus != 0 && (int)placementStatus != 12 && (int)placementStatus != 2 && ((int)placementStatus != 4 || _wards.Value) && ((int)placementStatus != 3 || _noBuild.Value) && (_noBuild.Value || !Location.IsInsideNoBuildLocation(placementGhost.transform.position)) && (_wards.Value || PrivateArea.CheckAccess(placementGhost.transform.position, 0f, false, false)))
					{
						__instance.m_placementStatus = (PlacementStatus)0;
						__instance.SetPlacementGhostValid(true);
					}
				}
			}
		}

		[HarmonyPatch(typeof(Player), "HaveRequirements", new Type[]
		{
			typeof(Piece),
			typeof(RequirementMode)
		})]
		internal static class StationPatch
		{
			[HarmonyPriority(800)]
			private static void Prefix(Player __instance, Piece piece, RequirementMode mode, out CraftingStation __state)
			{
				//IL_0003: Unknown result type (might be due to invalid IL or missing references)
				//IL_0058: Unknown result type (might be due to invalid IL or missing references)
				__state = null;
				if ((int)mode == 0 && !((Object)(object)piece == (Object)null) && !((Object)(object)piece.m_craftingStation == (Object)null) && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && _station.Value && !(Mode() != "Unrestricted (Cheat)") && !((Object)(object)CraftingStation.HaveBuildStationInRange(piece.m_craftingStation.m_name, ((Component)__instance).transform.position) != (Object)null))
				{
					__state = piece.m_craftingStation;
					piece.m_craftingStation = null;
				}
			}

			private static void Finalizer(Piece piece, CraftingStation __state)
			{
				if ((Object)(object)__state != (Object)null)
				{
					piece.m_craftingStation = __state;
				}
			}
		}

		private const string Section = "Building";

		private const string CheatSection = "Cheats: Building";

		internal const string Vanilla = "Vanilla";

		internal const string Accurate = "Accurate";

		internal const string Unrestricted = "Unrestricted (Cheat)";

		private static ConfigEntry<string> _mode;

		private static ConfigEntry<bool> _wards;

		private static ConfigEntry<bool> _noBuild;

		private static ConfigEntry<bool> _station;

		private static Player _placing;

		public static void Bind(ConfigFile cfg)
		{
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Expected O, but got Unknown
			_mode = cfg.Bind<string>("Building", "Build Restrictions", "Accurate", new ConfigDescription("Vanilla = every placement rule of the game. Accurate = station extensions (Chopping Block, Tanning Rack, Anvils and the like) may stand as close together as their own shapes allow, instead of 2 m apart; every other rule stays. Unrestricted (Cheat) = any spot where the piece shows is valid, except inside another player, with the choices in Cheats, Building.", (AcceptableValueBase)(object)new AcceptableValueList<string>(new string[3] { "Vanilla", "Accurate", "Unrestricted (Cheat)" }), Array.Empty<object>()));
			_wards = cfg.Bind<bool>("Cheats: Building", "Unrestricted Ignores Wards (Cheat)", false, "Cheat, off by default: with Build Restrictions on Unrestricted (Cheat), pieces may also be placed inside other players' wards.");
			_noBuild = cfg.Bind<bool>("Cheats: Building", "Unrestricted Ignores No-Build Zones (Cheat)", false, "Cheat, off by default: with Build Restrictions on Unrestricted (Cheat), pieces may be placed in the places the game keeps free of building (around traders, boss altars and the like).");
			_station = cfg.Bind<bool>("Cheats: Building", "Unrestricted Ignores Station Range (Cheat)", false, "Cheat, off by default: with Build Restrictions on Unrestricted (Cheat), pieces that need a crafting station nearby (a workbench for most) may be placed without one.");
		}

		internal static string Mode()
		{
			string text = _mode?.Value ?? "Vanilla";
			if (text == "Unrestricted (Cheat)" && !ServerRules.Allows("UnrestrictedBuilding"))
			{
				text = "Accurate";
			}
			if (text == "Accurate" && !ServerRules.Allows("AccuratePlacement"))
			{
				text = "Vanilla";
			}
			return text;
		}
	}
	internal static class BuildSections
	{
		[HarmonyPatch(typeof(TabHandler), "Update")]
		internal static class TabPatch
		{
			private static void Prefix(TabHandler __instance)
			{
				if (_on == null || !_on.Value || !Available)
				{
					return;
				}
				bool buttonDown = ZInput.GetButtonDown("TabLeft");
				bool buttonDown2 = ZInput.GetButtonDown("TabRight");
				if ((!buttonDown && !buttonDown2) || (Object)(object)((Component)__instance).GetComponentInParent<BuildUi>() == (Object)null || InventoryFeatures.Typing())
				{
					return;
				}
				object obj = TypingField?.GetValue(null);
				if (obj is bool && (bool)obj)
				{
					return;
				}
				object value = InstanceField.GetValue(null);
				if (value != null)
				{
					obj = ShownField.GetValue(value);
					if (obj is bool && (bool)obj)
					{
						StepMethod.Invoke(value, new object[1] { (!buttonDown) ? 1 : (-1) });
						ZInput.ResetButtonStatus(buttonDown ? "TabLeft" : "TabRight");
					}
				}
			}
		}

		private static readonly Type MenuType = TypeLookup.Find("SeneaLUI.Hud.BuildMenuView");

		private static readonly FieldInfo InstanceField = ((MenuType == null) ? null : AccessTools.Field(MenuType, "_instance"));

		private static readonly FieldInfo ShownField = ((MenuType == null) ? null : AccessTools.Field(MenuType, "_shown"));

		private static readonly FieldInfo TypingField = ((MenuType == null) ? null : AccessTools.Field(MenuType, "Typing"));

		private static readonly MethodInfo StepMethod = ((MenuType == null) ? null : AccessTools.Method(MenuType, "PadChip", new Type[1] { typeof(int) }, (Type[])null));

		private static ConfigEntry<bool> _on;

		public static bool Available
		{
			get
			{
				if (InstanceField != null && ShownField != null)
				{
					return StepMethod != null;
				}
				return false;
			}
		}

		public static void Bind(ConfigFile cfg)
		{
			_on = cfg.Bind<bool>("Building", "Q And E Change Section", false, "In the build menu, Q and E step through the sections beside the pieces (the category chips) instead of the four sorting tabs. Off, they change the tab as the game does.");
		}
	}
	internal static class CarryCheats
	{
		[HarmonyPatch(typeof(Player), "GetMaxCarryWeight")]
		internal static class WeightPatch
		{
			private static void Postfix(Player __instance, ref float __result)
			{
				if (_infinite != null && Local(__instance) && ServerRules.On(_infinite, "InfiniteCarry") && __result < 100000f)
				{
					__result = 100000f;
				}
			}
		}

		[HarmonyPatch(typeof(Player), "IsEncumbered")]
		internal static class EncumberedPatch
		{
			private static void Postfix(Player __instance, ref bool __result)
			{
				if (__result && _noEncumbrance != null && Local(__instance) && ServerRules.On(_noEncumbrance, "NoEncumbrance"))
				{
					__result = false;
				}
			}
		}

		private const string Section = "Cheats: Carrying";

		private const float Unlimited = 100000f;

		private static ConfigEntry<bool> _infinite;

		private static ConfigEntry<bool> _noEncumbrance;

		public static void Bind(ConfigFile cfg)
		{
			_infinite = cfg.Bind<bool>("Cheats: Carrying", "Infinite Carry Weight (Cheat)", false, "Cheat, off by default: your carry weight limit is 100000, so you are never encumbered and auto-pickup never stops for weight.");
			_noEncumbrance = cfg.Bind<bool>("Cheats: Carrying", "No Encumbrance (Cheat)", false, "Cheat, off by default: going over your carry weight never encumbers you (no slowdown, no stamina drain, running allowed), while the limit itself and auto-pickup stopping at it stay as the game has them.");
		}

		private static bool Local(Player player)
		{
			if ((Object)(object)player != (Object)null)
			{
				return (Object)(object)player == (Object)(object)Player.m_localPlayer;
			}
			return false;
		}
	}
	internal static class Cartography
	{
		[HarmonyPatch(typeof(Minimap), "AddSharedMapData")]
		internal static class ReadPatch
		{
			private static void Postfix(Minimap __instance)
			{
				//IL_0051: Unknown result type (might be due to invalid IL or missing references)
				//IL_0056: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
				//IL_00ac: 

SeneaLUIUnlocker.WindowAdditions.dll

Decompiled 2 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
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 BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SeneaLUI;
using SeneaLUI.Components;
using SeneaLUI.Core;
using SeneaLUI.Hud;
using SeneaLUI.Inv;
using SeneaLUI.Theme;
using TMPro;
using UnityEngine;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: IgnoresAccessChecksTo("assembly_utils")]
[assembly: IgnoresAccessChecksTo("assembly_valheim")]
[assembly: IgnoresAccessChecksTo("SeneaL-UI")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("SeneaLUIUnlocker.WindowAdditions")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.0.0")]
[assembly: AssemblyInformationalVersion("1.1.0+451f989c3bd01a2c60337d6c4277b6434ef2ce2a")]
[assembly: AssemblyProduct("SeneaLUIUnlocker.WindowAdditions")]
[assembly: AssemblyTitle("SeneaLUIUnlocker.WindowAdditions")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace SeneaLUIUnlocker
{
	internal sealed class BuiltInPreset : IBuiltInPreset
	{
		public const string Name = "SeneaL UI Unlocker";

		private const float SettleSeconds = 3f;

		private const string GrowCornersKey = "GrowCorners";

		private readonly ConfigEntry<bool> _applyFirst;

		private readonly ConfigFile _cfg;

		private readonly string _growCorners;

		private readonly ConfigEntry<bool> _checked;

		private readonly ManualLogSource _log;

		private readonly Dictionary<string, string> _values;

		private readonly Dictionary<string, string> _looks;

		private GameObject _row;

		private float _hudSince = -1f;

		private BuiltInPreset(ConfigFile cfg, ManualLogSource log, Dictionary<string, string> values, Dictionary<string, string> looks)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			_cfg = cfg;
			_log = log;
			_values = values;
			_growCorners = (looks.TryGetValue("GrowCorners", out var value) ? value : null);
			looks.Remove("GrowCorners");
			_looks = looks;
			_applyFirst = cfg.Bind<bool>("Interface", "Use SeneaL UI Unlocker Layout At First", true, "On the first world after installing, give the SeneaL UI Unlocker interface preset to a layout that is still SeneaL UI's default or one of its built-in presets. A layout you changed or saved is never touched. The preset is also in the HUD editor's Interfaces menu.");
			_checked = cfg.Bind<bool>("Interface", "First Layout Checked", false, new ConfigDescription("Whether the first-world layout check has run, kept by the mod.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				Browsable = false
			} }));
		}

		public static IBuiltInPreset Create(ConfigFile cfg, ManualLogSource log)
		{
			using Stream stream = typeof(BuiltInPreset).Assembly.GetManifestResourceStream("SeneaLUIUnlocker.Preset.slui");
			string text = ((stream == null) ? null : new StreamReader(stream).ReadToEnd());
			string text2 = default(string);
			Dictionary<string, string> values = default(Dictionary<string, string>);
			if (text == null || !Profiles.Parse(text, ref text2, ref values))
			{
				throw new InvalidDataException("The bundled interface preset could not be read.");
			}
			using Stream stream2 = typeof(BuiltInPreset).Assembly.GetManifestResourceStream("SeneaLUIUnlocker.PresetLooks.txt");
			Dictionary<string, string> dictionary = new Dictionary<string, string>();
			string[] array = ((stream2 == null) ? "" : new StreamReader(stream2).ReadToEnd()).Split(new char[1] { '\n' });
			foreach (string text3 in array)
			{
				int num = text3.IndexOf('=');
				if (num > 0)
				{
					dictionary[text3.Substring(0, num).Trim()] = text3.Substring(num + 1).Trim();
				}
			}
			return (IBuiltInPreset)(object)new BuiltInPreset(cfg, log, values, dictionary);
		}

		public void Tick()
		{
			FirstLayout();
			HudEditor i = HudEditor._i;
			ProfileMenu val = (((Object)(object)i == (Object)null || !i._built) ? null : i._profiles);
			if (val != null && val.Open && !((Object)(object)_row != (Object)null))
			{
				Insert(val);
			}
		}

		private void Apply(ProfileMenu menu)
		{
			if (menu != null)
			{
				menu.Remember();
			}
			Profiles.Apply(_values, true);
			ElementLook.SetLooks((IReadOnlyDictionary<string, string>)_looks);
			ConfigEntry<string> val = default(ConfigEntry<string>);
			if (_growCorners != null && _cfg.TryGetEntry<string>("HUD Editor", "Grow Corners", ref val))
			{
				val.Value = _growCorners;
			}
			CraftingPlacement current = CraftingPlacement.Current;
			if (current != null)
			{
				current.Forget();
			}
			LayoutArea.Adopt();
			if (menu != null)
			{
				menu.Done("SeneaL UI Unlocker", Loc.HudProfApplied);
			}
			else
			{
				Prefs.ActiveProfile.Value = "SeneaL UI Unlocker";
			}
		}

		private void FirstLayout()
		{
			if (_checked.Value || Prefs.Cfg == null || (Object)(object)Hud.instance == (Object)null || !HudRoot.Built)
			{
				_hudSince = -1f;
				return;
			}
			if (_hudSince < 0f)
			{
				_hudSince = Time.unscaledTime;
			}
			if (Time.unscaledTime - _hudSince < 3f)
			{
				return;
			}
			_checked.Value = true;
			if (_applyFirst.Value)
			{
				Dictionary<string, string> now = Profiles.Changed(Profiles.Capture());
				if (now.Count != 0 && !Profiles.PresetIds.Any((string id) => Same(now, Profiles.Changed(Profiles.Preset(id)))))
				{
					_log.LogInfo((object)"Kept the player's own interface layout; the SeneaL UI Unlocker preset is in the Interfaces menu.");
					return;
				}
				Apply(null);
				_log.LogInfo((object)"Gave the untouched interface layout the SeneaL UI Unlocker preset.");
			}
		}

		private static bool Same(Dictionary<string, string> a, Dictionary<string, string> b)
		{
			string value;
			if (a.Count == b.Count)
			{
				return a.All((KeyValuePair<string, string> pair) => b.TryGetValue(pair.Key, out value) && value == pair.Value);
			}
			return false;
		}

		private void Insert(ProfileMenu menu)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Expected O, but got Unknown
			//IL_006c: 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_00a3: Expected O, but got Unknown
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0149: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0108: Unknown result type (might be due to invalid IL or missing references)
			//IL_010d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0204: 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)
			List<GameObject> rows = menu._rows;
			int num = Profiles.PresetIds.Length;
			if (rows == null || rows.Count < num + 1 || (Object)(object)rows[1] == (Object)null)
			{
				return;
			}
			RectTransform val = (RectTransform)rows[1].transform;
			RectTransform val2 = (RectTransform)rows[num].transform;
			float y = val.sizeDelta.y;
			_row = Object.Instantiate<GameObject>(rows[1], ((Transform)val).parent, false);
			RectTransform val3 = (RectTransform)_row.transform;
			val3.anchoredPosition = val2.anchoredPosition - new Vector2(0f, y);
			((Transform)val3).SetSiblingIndex(((Transform)val2).GetSiblingIndex() + 1);
			for (int i = num + 1; i < rows.Count; i++)
			{
				if ((Object)(object)rows[i] != (Object)null)
				{
					RectTransform val4 = (RectTransform)rows[i].transform;
					val4.anchoredPosition -= new Vector2(0f, y);
				}
			}
			rows.Add(_row);
			RectTransform content = menu._scroll.Content;
			content.sizeDelta = new Vector2(content.sizeDelta.x, content.sizeDelta.y + y);
			bool active = Prefs.ActiveProfile != null && Prefs.ActiveProfile.Value == "SeneaL UI Unlocker";
			TextMeshProUGUI[] componentsInChildren = _row.GetComponentsInChildren<TextMeshProUGUI>(true);
			foreach (TextMeshProUGUI val5 in componentsInChildren)
			{
				switch (((Object)((Component)val5).gameObject).name)
				{
				case "t":
					((TMP_Text)val5).text = "SeneaL UI Unlocker";
					((Graphic)val5).color = (active ? Palette.Gold : Palette.Linen);
					break;
				case "d":
					((TMP_Text)val5).text = Lang.T("BuiltInPreset.Description", "SeneaL UI's layout with this mod's cards and windows placed");
					break;
				case "by":
					((TMP_Text)val5).text = string.Format(Loc.HudProfBy, "Alkeari");
					break;
				}
			}
			Transform val6 = ((Transform)val3).Find("bg");
			Image highlight = ((val6 != null) ? ((Component)val6).GetComponent<Image>() : null);
			if ((Object)(object)highlight != (Object)null)
			{
				highlight.sprite = Skin.Sliced(34, active ? Styles.RowOn : Styles.RowHover, -1);
				((Behaviour)highlight).enabled = active;
			}
			UIInputHandler component = _row.GetComponent<UIInputHandler>();
			component.m_onPointerEnter = delegate
			{
				if ((Object)(object)highlight != (Object)null && !active)
				{
					((Behaviour)highlight).enabled = true;
				}
			};
			component.m_onPointerExit = delegate
			{
				if ((Object)(object)highlight != (Object)null && !active)
				{
					((Behaviour)highlight).enabled = false;
				}
			};
			component.m_onLeftClick = delegate
			{
				if (Plugin.Active)
				{
					Click.Play();
					Apply(menu);
				}
			};
		}
	}
	internal sealed class EditorAdditions : IEditorBridge
	{
		private sealed class Row
		{
			public readonly RectTransform Root;

			public readonly int Index;

			private readonly bool? _station;

			private readonly TextMeshProUGUI _name;

			private readonly Tb _show;

			private readonly Tb _lock;

			private readonly Tb _pick;

			public Row(EditorAdditions owner, RectTransform parent, int index, bool? station, float width)
			{
				//IL_0073: Unknown result type (might be due to invalid IL or missing references)
				//IL_0132: Unknown result type (might be due to invalid IL or missing references)
				//IL_017f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0189: Expected O, but got Unknown
				//IL_0201: Unknown result type (might be due to invalid IL or missing references)
				//IL_020b: Expected O, but got Unknown
				//IL_0283: Unknown result type (might be due to invalid IL or missing references)
				//IL_028d: Expected O, but got Unknown
				Index = index;
				_station = station;
				Root = Ui.TL((Transform)(object)parent, "row" + index, 0f, 0f, width, 28f);
				((Graphic)Ui.Img(Root, (Sprite)null, Palette.Clear)).raycastTarget = true;
				((Component)Root).gameObject.AddComponent<DragSurface>().OnDown = delegate
				{
					if (station.HasValue)
					{
						bool valueOrDefault = station == true;
						CraftingPlacement current = CraftingPlacement.Current;
						if (current != null)
						{
							current.Edit(valueOrDefault);
						}
					}
					Open(index);
				};
				Tooltip.Bind(Root, (Func<Tip>)(() => station.HasValue ? ((station == true) ? Tips.Text(new Tip(), Lang.T("EditorAdditions.CraftStation", "Crafting: Station"), Lang.T("EditorAdditions.CraftStationTip", "Select where the Crafting window sits while you use a crafting station, where SeneaL UI draws it wider; it starts where the inventory one is until you move it.")) : Tips.Text(new Tip(), Lang.T("EditorAdditions.CraftInventory", "Crafting: Inventory"), Lang.T("EditorAdditions.CraftInventoryTip", "Select where the Crafting window sits beside your inventory away from a crafting station."))) : Tips.Text(new Tip(), Lang.T("EditorAdditions.Select", "Select"), Lang.T("EditorAdditions.SelectTip", "Select this element and open its settings."))), (RectTransform)null);
				_name = Ui.Label((Transform)(object)Root, "name", TextStyles.CardLabel, 0f, 4f, 19f, width - 116f, (TextAlignmentOptions)513);
				((Graphic)_name).raycastTarget = false;
				((Graphic)Ui.Img(Ui.TL((Transform)(object)Root, "rule", 0f, 27f, width, 1f), (Sprite)null, Palette.Rgba(214, 178, 110, 0.16f))).raycastTarget = false;
				_show = new Tb((Transform)(object)Root, "show", "eye", (Action)delegate
				{
					EditTarget obj = Editor._targets[index];
					obj.Shown = !obj.Shown;
				}, (Func<Tip>)(() => Tips.Text(new Tip(), Lang.T("EditorAdditions.Show", "Show"), Lang.T("EditorAdditions.ShowTip", "Show or hide this element in play."))), (Action)null);
				_show.SetLabel((string)null);
				Ui.Place(_show.Root, 1f, 0.5f, -40f, 0f, 30f, 26f);
				_pick = new Tb((Transform)(object)Root, "pick", "check", (Action)delegate
				{
					owner.TogglePick(Editor._targets[index]);
				}, (Func<Tip>)(() => Tips.Text(new Tip(), Lang.T("EditorAdditions.Pick", "Pick"), Lang.T("EditorAdditions.PickTip", "Pick this element to line it up or space it evenly with the other picked elements."))), (Action)null);
				_pick.SetLabel((string)null);
				Ui.Place(_pick.Root, 1f, 0.5f, -76f, 0f, 30f, 26f);
				_lock = new Tb((Transform)(object)Root, "lock", "lock", (Action)delegate
				{
					owner.ToggleLock(Editor._targets[index]);
				}, (Func<Tip>)(() => Tips.Text(new Tip(), Lang.T("EditorAdditions.Lock", "Lock"), Lang.T("EditorAdditions.LockTip", "Lock this element in place: it can still be selected and set, but not moved."))), (Action)null);
				_lock.SetLabel((string)null);
				Ui.Place(_lock.Root, 1f, 0.5f, -4f, 0f, 30f, 26f);
			}

			public static string Title(EditTarget target, bool? station)
			{
				if (station.HasValue)
				{
					if (station != true)
					{
						return Lang.T("EditorAdditions.CraftInventory", "Crafting: Inventory");
					}
					return Lang.T("EditorAdditions.CraftStation", "Crafting: Station");
				}
				return target.Name ?? "";
			}

			private static void Open(int index)
			{
				HudEditor editor = Editor;
				editor.Select(index);
				editor.Focus();
			}

			public void Sync(HudEditor editor, bool locked, bool picked)
			{
				//IL_0094: Unknown result type (might be due to invalid IL or missing references)
				//IL_008d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0086: Unknown result type (might be due to invalid IL or missing references)
				_pick.SetLit(picked);
				EditTarget val = editor._targets[Index];
				((TMP_Text)_name).text = Title(val, _station);
				int num;
				if (Index == editor._sel)
				{
					bool? station = _station;
					if (station.HasValue)
					{
						bool valueOrDefault = station == true;
						num = ((CraftingPlacement.Current != null && CraftingPlacement.Current.EditingStation == valueOrDefault) ? 1 : 0);
					}
					else
					{
						num = 1;
					}
				}
				else
				{
					num = 0;
				}
				bool flag = (byte)num != 0;
				((Graphic)_name).color = (flag ? Palette.Gold : (val.Editable ? Palette.Parchment : Palette.Ash));
				_show.SetIcon(val.Shown ? "eye" : "eyeoff", false);
				_lock.SetLit(locked);
			}
		}

		private const float PanelWidth = 300f;

		private const float RowHeight = 28f;

		private const float Pad = 12f;

		private const float BarSlot = 478f;

		private const float BarStep = 44f;

		private readonly ConfigEntry<bool> _enabled;

		private readonly ConfigEntry<string> _locked;

		private readonly ConfigEntry<bool> _panelOpen;

		private readonly ConfigEntry<bool> _showOthers;

		private readonly ConfigEntry<bool> _fitFrames;

		private bool _fitBroken;

		private UIInputHandler _othersHooked;

		private readonly ManualLogSource _log;

		private readonly ConfigFile _cfg;

		private const float PanelHeight = 600f;

		private bool _broken;

		private GameObject _canvas;

		private RectTransform _bar;

		private EditTarget[] _targets;

		private float _fitted;

		private Tb _button;

		private RectTransform _panel;

		private SearchBox _search;

		private ScrollBox _scroll;

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

		private Elem _demoOn;

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

		private ElementSelect _align;

		private bool _alignShown;

		private bool _targetsBroken;

		private OwnerSwitch _modes;

		private RectTransform _modesBar;

		private int _modeShown = -1;

		private bool _other;

		private ElementMode _listedMode = (ElementMode)(-1);

		private bool _panelMoved;

		private RectTransform _inspHooked;

		private Vector2 _inspAt;

		private bool _inspMoved;

		private int _seenSel = -1;

		private string _filter = "";

		private bool _dirty = true;

		private readonly Dictionary<RectTransform, (Action<Vector2> Down, Action<Vector2> Move, Action Up)> _original = new Dictionary<RectTransform, (Action<Vector2>, Action<Vector2>, Action)>();

		private readonly Dictionary<string, string[]> _lockedPlace = new Dictionary<string, string[]>();

		private static readonly FieldInfo InspectorField = AccessTools.Field(typeof(HudEditor), "_insp");

		private static readonly FieldInfo InspectorMap = ((InspectorField == null) ? null : AccessTools.Field(InspectorField.FieldType, "_map"));

		private static readonly FieldInfo InspectorOptions = ((InspectorField == null) ? null : AccessTools.Field(InspectorField.FieldType, "_opts"));

		private static readonly FieldInfo AttachCandidates = AccessTools.Field(typeof(EditTarget), "Candidates");

		private static readonly string[] LookFields = new string[28]
		{
			"Size", "TextK", "AlphaK", "BackK", "Variant", "Readout", "CapSide", "CapColor", "CapStyle", "CapSize",
			"Ticks", "VerticalE", "ReverseE", "Fixed", "Angle", "Thick", "LenLo", "LenHi", "LenAt", "TintS",
			"AccentS", "HideEmptyK", "Anim", "Style", "Transp", "ReadAt", "KeyShow", "Lack"
		};

		private Dictionary<string, object> _look;

		private string _lookFrom;

		private static readonly FieldInfo ObjectsField = typeof(HudEditor).GetField("_objects", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);

		private static readonly Type ObjectsType = ObjectsField?.FieldType;

		private static readonly PropertyInfo ObjectsOpen = ((ObjectsType == null) ? null : AccessTools.Property(ObjectsType, "Open"));

		private static readonly FieldInfo ObjectsPop = ((ObjectsType == null) ? null : AccessTools.Field(ObjectsType, "_pop"));

		private static readonly FieldInfo ObjectsRows = ((ObjectsType == null) ? null : AccessTools.Field(ObjectsType, "_rows"));

		private static readonly FieldInfo ObjectsList = ((ObjectsType == null) ? null : AccessTools.Field(ObjectsType, "_list"));

		private const float ToolGap = 6f;

		private const float GridWidth = 108f;

		private readonly Dictionary<GameObject, (int Index, Tb Lock, Tb Pick, Tb Station)> _objectRows = new Dictionary<GameObject, (int, Tb, Tb, Tb)>();

		private RectTransform _objectsTools;

		private RectTransform _arrangeGrid;

		private RectTransform _toolsPop;

		private float _popSet = -1f;

		private float _listHeight;

		private bool _arrangeShown;

		private int _firstRow;

		private int _rowCount = -1;

		private static readonly bool SeneaLListsObjects = ObjectsField != null && ObjectsOpen?.PropertyType == typeof(bool) && ObjectsPop?.FieldType == typeof(RectTransform) && ObjectsRows?.FieldType == typeof(List<GameObject>) && ObjectsList?.FieldType == typeof(List<int>);

		private static HudEditor Editor => HudEditor._i;

		private static string[] AlignNames => new string[9]
		{
			Lang.T("EditorAdditions.AlignLeft", "Align Left Edges"),
			Lang.T("EditorAdditions.AlignCentersAcross", "Align Centers Across"),
			Lang.T("EditorAdditions.AlignRight", "Align Right Edges"),
			Lang.T("EditorAdditions.AlignTop", "Align Top Edges"),
			Lang.T("EditorAdditions.AlignCentersDown", "Align Centers Down"),
			Lang.T("EditorAdditions.AlignBottom", "Align Bottom Edges"),
			Lang.T("EditorAdditions.SpaceAcross", "Space Evenly Across"),
			Lang.T("EditorAdditions.SpaceDown", "Space Evenly Down"),
			Lang.T("EditorAdditions.ClearPicked", "Clear Picked Elements")
		};

		private static string[] ArrangeLabels => new string[9]
		{
			Lang.T("ObjectsList.AlignLeft", "Align Left"),
			Lang.T("ObjectsList.AlignCenter", "Align Center"),
			Lang.T("ObjectsList.AlignRight", "Align Right"),
			Lang.T("ObjectsList.AlignTop", "Align Top"),
			Lang.T("ObjectsList.AlignMiddle", "Align Middle"),
			Lang.T("ObjectsList.AlignBottom", "Align Bottom"),
			Lang.T("ObjectsList.SpaceAcross", "Space Across"),
			Lang.T("ObjectsList.SpaceDown", "Space Down"),
			Lang.T("ObjectsList.ClearPicks", "Clear Picks")
		};

		private static string[] ArrangeTips => new string[9]
		{
			Lang.T("ObjectsList.AlignLeftTip", "Move the picked elements so their left edges line up with the first one picked."),
			Lang.T("ObjectsList.AlignCenterTip", "Move the picked elements so their centers line up across with the first one picked."),
			Lang.T("ObjectsList.AlignRightTip", "Move the picked elements so their right edges line up with the first one picked."),
			Lang.T("ObjectsList.AlignTopTip", "Move the picked elements so their top edges line up with the first one picked."),
			Lang.T("ObjectsList.AlignMiddleTip", "Move the picked elements so their centers line up down with the first one picked."),
			Lang.T("ObjectsList.AlignBottomTip", "Move the picked elements so their bottom edges line up with the first one picked."),
			Lang.T("ObjectsList.SpaceAcrossTip", "Space the picked elements evenly across, between the outermost two."),
			Lang.T("ObjectsList.SpaceDownTip", "Space the picked elements evenly down, between the outermost two."),
			Lang.T("ObjectsList.ClearPicksTip", "Unpick every picked element.")
		};

		private EditorAdditions(ConfigFile cfg, ConfigEntry<bool> enabled, ConfigEntry<string> locked, ConfigEntry<bool> panelOpen, ConfigEntry<bool> showOthers, ConfigEntry<bool> fitFrames, ManualLogSource log)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected O, but got Unknown
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Expected O, but got Unknown
			//IL_00d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Expected O, but got Unknown
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Expected O, but got Unknown
			_cfg = cfg;
			_showOthers = showOthers;
			_fitFrames = fitFrames;
			Canvas.willRenderCanvases += new WillRenderCanvases(FitFrames);
			_enabled = enabled;
			_locked = locked;
			_panelOpen = panelOpen;
			_log = log;
			Canvas.willRenderCanvases += new WillRenderCanvases(PlaceInspector);
			Canvas.willRenderCanvases += new WillRenderCanvases(HideForOther);
			Canvas.willRenderCanvases += new WillRenderCanvases(KeepListsInMode);
		}

		public static EditorAdditions Create(ConfigFile cfg, ManualLogSource log)
		{
			//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_0047: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Expected O, but got Unknown
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//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_00b5: Expected O, but got Unknown
			//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Expected O, but got Unknown
			ConfigEntry<bool> enabled = cfg.Bind<bool>("HUD Editor", "Editor Additions", true, "Add an Elements button to SeneaL UI's HUD editor bar: a list of every element with search, show and lock; clicking one opens its settings panel and shows it with sample content where SeneaL UI has one.");
			ConfigEntry<string> locked = cfg.Bind<string>("HUD Editor", "Locked Elements", "", new ConfigDescription("Elements locked in the HUD editor, kept by the mod.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				Browsable = false
			} }));
			ConfigEntry<bool> panelOpen = cfg.Bind<bool>("HUD Editor", "Elements Panel Open", false, new ConfigDescription("Whether the Elements panel was open, kept by the mod.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				Browsable = false
			} }));
			ConfigEntry<bool> showOthers = cfg.Bind<bool>("HUD Editor", "Show Other Elements", false, new ConfigDescription("The state of the HUD editor's Others button, kept by the mod so it stays as you set it.", (AcceptableValueBase)null, new object[1] { (object)new ConfigurationManagerAttributes
			{
				Browsable = false
			} }));
			ConfigEntry<bool> fitFrames = cfg.Bind<bool>("HUD Editor", "Frames Match Elements", true, "Draw each frame in SeneaL UI's HUD editor exactly around its element instead of 5 units outside it, so elements placed edge to edge show frames that touch rather than overlap.");
			_ = HudEditor.Open;
			ElementContent.Bind(cfg);
			return new EditorAdditions(cfg, enabled, locked, panelOpen, showOthers, fitFrames, log);
		}

		private bool Ready(out HudEditor editor)
		{
			editor = Editor;
			if (_enabled.Value && ServerRules.Allows("EditorAdditions") && (Object)(object)editor != (Object)null && editor._built && editor._targets != null)
			{
				return (Object)(object)editor._bar != (Object)null;
			}
			return false;
		}

		public void Tick()
		{
			if (_broken)
			{
				return;
			}
			try
			{
				Step();
			}
			catch (Exception arg)
			{
				_broken = true;
				if ((Object)(object)_canvas != (Object)null)
				{
					_canvas.SetActive(false);
				}
				_log.LogWarning((object)$"The HUD editor additions stopped after an error and stay off until the game restarts; SeneaL UI's editor is unaffected: {arg}");
			}
		}

		private void Step()
		{
			//IL_011b: 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)
			//IL_0138: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0168: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c6: Unknown result type (might be due to invalid IL or missing references)
			if (!Ready(out var editor))
			{
				if ((Object)(object)_canvas != (Object)null)
				{
					_canvas.SetActive(false);
				}
				if (_button != null && (Object)(object)_button.Root != (Object)null && (!_enabled.Value || !ServerRules.Allows("EditorAdditions")))
				{
					((Component)_button.Root).gameObject.SetActive(false);
				}
				return;
			}
			bool seneaLListsObjects = SeneaLListsObjects;
			if (!seneaLListsObjects && (_button == null || (Object)(object)_button.Root == (Object)null || (Object)(object)_bar != (Object)(object)editor._bar))
			{
				BuildButton(editor);
			}
			if (!seneaLListsObjects && !((Component)_button.Root).gameObject.activeSelf)
			{
				((Component)_button.Root).gameObject.SetActive(true);
			}
			RectTransform val = ((editor._othersBtn == null) ? null : editor._othersBtn.Root);
			if (!seneaLListsObjects && (Object)(object)val != (Object)null)
			{
				float num = (((Component)val).gameObject.activeSelf ? (val.anchoredPosition.x + 44f) : val.anchoredPosition.x);
				if (_button.Root.anchoredPosition.x != num)
				{
					_button.Root.anchoredPosition = new Vector2(num, _button.Root.anchoredPosition.y);
				}
			}
			HookOthers(editor);
			KeepOthers(editor);
			HookInspector(editor);
			if (_targets != editor._targets)
			{
				if (!_targetsBroken)
				{
					try
					{
						for (int i = 0; i < editor._targets.Length; i++)
						{
							if (ElementTarget.Ours(editor._targets[i]))
							{
								editor._targets[i] = (EditTarget)(object)new ElementTarget(((ExtTarget)editor._targets[i])._rig);
							}
						}
					}
					catch (Exception ex)
					{
						_targetsBroken = true;
						_log.LogWarning((object)("This plugin's elements could not get their full settings panels; they keep SeneaL UI's plain one: " + ex.GetBaseException().Message));
					}
				}
				_targets = editor._targets;
				_original.Clear();
				_dirty = true;
			}
			if ((Object)(object)_canvas == (Object)null)
			{
				BuildPanel(editor);
			}
			Modes(editor);
			bool flag = !seneaLListsObjects && editor._open && _panelOpen.Value;
			if (_canvas.activeSelf != flag)
			{
				_canvas.SetActive(flag);
			}
			if (!editor._open)
			{
				if (_demoOn != null)
				{
					HudEditor.SetDemo(_demoOn, false);
					_demoOn = null;
				}
				_seenSel = -1;
				return;
			}
			if (seneaLListsObjects)
			{
				ExtendObjects(editor);
			}
			else
			{
				_button.SetLit(_panelOpen.Value);
			}
			ShowSample(editor);
			if (!flag)
			{
				return;
			}
			Fit(editor);
			_search.Tick(false);
			if (_dirty)
			{
				Rebuild(editor);
			}
			foreach (Row row in _rows)
			{
				row.Sync(editor, Locked(editor._targets[row.Index]), Picked(editor._targets[row.Index]));
			}
			if (_align != null && _alignShown)
			{
				_align.Tick((Component)(object)_canvas.GetComponent<Canvas>());
			}
			if (_align == null || !_align.Open)
			{
				_scroll.Tick((Component)(object)editor);
			}
		}

		private bool Picked(EditTarget t)
		{
			if (t.E != null)
			{
				return _picked.Contains(t.E.Key);
			}
			return false;
		}

		private void TogglePick(EditTarget t)
		{
			if (t.E != null)
			{
				if (!_picked.Remove(t.E.Key))
				{
					_picked.Add(t.E.Key);
				}
				_fitted = -1f;
			}
		}

		private void Arrange(HudEditor editor, int how)
		{
			//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_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0114: Unknown result type (might be due to invalid IL or missing references)
			//IL_0119: Unknown result type (might be due to invalid IL or missing references)
			//IL_0285: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_0306: Unknown result type (might be due to invalid IL or missing references)
			//IL_030b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0323: Unknown result type (might be due to invalid IL or missing references)
			//IL_0328: Unknown result type (might be due to invalid IL or missing references)
			//IL_0333: Unknown result type (might be due to invalid IL or missing references)
			//IL_033f: Unknown result type (might be due to invalid IL or missing references)
			//IL_034a: Unknown result type (might be due to invalid IL or missing references)
			//IL_034f: Unknown result type (might be due to invalid IL or missing references)
			//IL_036e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0370: Unknown result type (might be due to invalid IL or missing references)
			//IL_037a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0367: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0244: Unknown result type (might be due to invalid IL or missing references)
			//IL_0249: Unknown result type (might be due to invalid IL or missing references)
			//IL_0227: Unknown result type (might be due to invalid IL or missing references)
			//IL_022c: Unknown result type (might be due to invalid IL or missing references)
			if (how == 8)
			{
				_picked.Clear();
				_fitted = -1f;
				return;
			}
			List<EditTarget> list = (from t in editor._targets
				where Picked(t) && !t.E.Glued
				orderby _picked.IndexOf(t.E.Key)
				select t).ToList();
			if (list.Count < 2)
			{
				return;
			}
			List<Rect> frames = list.Select((EditTarget t) => t.Frame()).ToList();
			Rect val = frames[0];
			if (how >= 6)
			{
				bool across = how == 6;
				List<int> list2 = Enumerable.Range(0, list.Count).OrderBy(delegate(int i)
				{
					//IL_0033: 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_003b: Unknown result type (might be due to invalid IL or missing references)
					//IL_0014: Unknown result type (might be due to invalid IL or missing references)
					//IL_0019: Unknown result type (might be due to invalid IL or missing references)
					//IL_001c: Unknown result type (might be due to invalid IL or missing references)
					Rect val6;
					if (!across)
					{
						val6 = frames[i];
						return ((Rect)(ref val6)).center.y;
					}
					val6 = frames[i];
					return ((Rect)(ref val6)).center.x;
				}).ToList();
				Rect val2 = frames[list2[0]];
				Rect val3 = frames[list2[list2.Count - 1]];
				float num = (across ? (((Rect)(ref val3)).xMax - ((Rect)(ref val2)).xMin) : (((Rect)(ref val3)).yMax - ((Rect)(ref val2)).yMin));
				float num2 = list2.Sum(delegate(int i)
				{
					//IL_002e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0033: Unknown result type (might be due to invalid IL or missing references)
					//IL_0014: Unknown result type (might be due to invalid IL or missing references)
					//IL_0019: Unknown result type (might be due to invalid IL or missing references)
					Rect val6;
					if (!across)
					{
						val6 = frames[i];
						return ((Rect)(ref val6)).height;
					}
					val6 = frames[i];
					return ((Rect)(ref val6)).width;
				});
				float num3 = (num - num2) / (float)(list2.Count - 1);
				float num4 = (across ? ((Rect)(ref val2)).xMin : ((Rect)(ref val2)).yMin);
				{
					foreach (int item in list2)
					{
						Rect val4;
						float num5;
						if (!across)
						{
							val4 = frames[item];
							num5 = ((Rect)(ref val4)).yMin;
						}
						else
						{
							val4 = frames[item];
							num5 = ((Rect)(ref val4)).xMin;
						}
						float num6 = num5;
						Shift(list[item], across ? new Vector2(num4 - num6, 0f) : new Vector2(0f, num4 - num6));
						float num7 = num4;
						float num8;
						if (!across)
						{
							val4 = frames[item];
							num8 = ((Rect)(ref val4)).height;
						}
						else
						{
							val4 = frames[item];
							num8 = ((Rect)(ref val4)).width;
						}
						num4 = num7 + (num8 + num3);
					}
					return;
				}
			}
			for (int num9 = 1; num9 < list.Count; num9++)
			{
				Rect val5 = frames[num9];
				Vector2 delta = (Vector2)(how switch
				{
					0 => new Vector2(((Rect)(ref val)).xMin - ((Rect)(ref val5)).xMin, 0f), 
					1 => new Vector2(((Rect)(ref val)).center.x - ((Rect)(ref val5)).center.x, 0f), 
					2 => new Vector2(((Rect)(ref val)).xMax - ((Rect)(ref val5)).xMax, 0f), 
					3 => new Vector2(0f, ((Rect)(ref val)).yMax - ((Rect)(ref val5)).yMax), 
					4 => new Vector2(0f, ((Rect)(ref val)).center.y - ((Rect)(ref val5)).center.y), 
					_ => new Vector2(0f, ((Rect)(ref val)).yMin - ((Rect)(ref val5)).yMin), 
				});
				Shift(list[num9], delta);
			}
		}

		private static void Shift(EditTarget t, Vector2 delta)
		{
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b3: 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_00b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			Elem e = t.E;
			if (e.PosX == null || e.PosY == null || ((Vector2)(ref delta)).sqrMagnitude < 0.25f)
			{
				return;
			}
			Vector2 val = default(Vector2);
			if (e.PosX.Value >= 0f && e.PosY.Value >= 0f)
			{
				((Vector2)(ref val))..ctor(e.PosX.Value * (float)Screen.width, e.PosY.Value * (float)Screen.height);
			}
			else if (e.Grow != null && e.Grow.Value >= 1)
			{
				val = e.GrowPoint(t.Frame());
			}
			else
			{
				if (e.LiveRef == null)
				{
					return;
				}
				val = e.LiveRef();
			}
			Vector2 val2 = val + delta;
			e.PosX.Value = Mathf.Clamp01(val2.x / (float)Screen.width);
			e.PosY.Value = Mathf.Clamp01(val2.y / (float)Screen.height);
		}

		public void LateTick()
		{
			if (_broken || !Ready(out var editor) || !editor._open || editor._frames == null)
			{
				return;
			}
			KeepOthers(editor);
			for (int i = 0; i < editor._targets.Length && i < editor._frames.Length; i++)
			{
				bool flag = Locked(editor._targets[i]);
				Hold(editor, i, flag);
				if (flag)
				{
					KeepPlace(editor._targets[i].E);
				}
				else
				{
					_lockedPlace.Remove(editor._targets[i].E.Key);
				}
			}
		}

		private void FitFrames()
		{
			HudEditor editor = Editor;
			if (_broken || _fitBroken || !_fitFrames.Value || (Object)(object)editor == (Object)null || !editor._open || editor._frames == null || editor._last == null)
			{
				return;
			}
			try
			{
				for (int i = 0; i < editor._frames.Length; i++)
				{
					Fit(editor, i);
				}
			}
			catch (Exception ex)
			{
				_fitBroken = true;
				_log.LogWarning((object)("Frames Match Elements stopped after an error and stays off until the game restarts: " + ex.GetBaseException().Message));
			}
		}

		private static void Fit(HudEditor editor, int i)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = editor._frames[i];
			if (!((Object)(object)val == (Object)null) && ((Component)val).gameObject.activeSelf && i < editor._last.Length)
			{
				Rect val2 = editor._last[i];
				if (!(((Rect)(ref val2)).width <= 0f) && !(((Rect)(ref val2)).height <= 0f) && (!(val.anchoredPosition == ((Rect)(ref val2)).min) || !(val.sizeDelta == ((Rect)(ref val2)).size)))
				{
					Ui.Place(val, 0f, 0f, ((Rect)(ref val2)).xMin, ((Rect)(ref val2)).yMin, ((Rect)(ref val2)).width, ((Rect)(ref val2)).height);
				}
			}
		}

		private void HookOthers(HudEditor editor)
		{
			UIInputHandler val = ((editor._othersBtn == null || (Object)(object)editor._othersBtn.Root == (Object)null) ? null : ((Component)editor._othersBtn.Root).GetComponent<UIInputHandler>());
			if ((Object)(object)val == (Object)null || (Object)(object)val == (Object)(object)_othersHooked)
			{
				return;
			}
			_othersHooked = val;
			val.m_onLeftClick = (Action<UIInputHandler>)Delegate.Combine(val.m_onLeftClick, (Action<UIInputHandler>)delegate
			{
				if ((Object)(object)Editor != (Object)null)
				{
					_showOthers.Value = Editor._showAll;
				}
			});
		}

		private void KeepOthers(HudEditor editor)
		{
			if (editor._open && editor._showAll != _showOthers.Value)
			{
				editor._showAll = _showOthers.Value;
			}
		}

		private ElementMode CurrentMode(HudEditor editor)
		{
			if (editor._open)
			{
				if (!_other)
				{
					if (editor._tabMode)
					{
						return (ElementMode)1;
					}
					return (ElementMode)0;
				}
				return (ElementMode)2;
			}
			return (ElementMode)0;
		}

		private void Modes(HudEditor editor)
		{
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Invalid comparison between Unknown and I4
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Expected I4, but got Unknown
			if (!editor._open)
			{
				_other = false;
			}
			if (_modes == null || (Object)(object)_modes.Root == (Object)null || (Object)(object)_modesBar != (Object)(object)editor._bar)
			{
				_modesBar = editor._bar;
				_modes = new OwnerSwitch((Transform)(object)editor._bar, "unlocker.mode", new string[3]
				{
					Loc.HudModeHud,
					Loc.HudModeTab,
					"Other"
				}, (Action<int>)PickMode, 140f);
				Tooltip.Bind(_modes.Root, (Func<Tip>)(() => Tips.Text(new Tip(), Lang.T("EditorAdditions.ModeTitle", "Editor Mode"), Lang.T("EditorAdditions.ModeTip", "HUD places what shows in play, Tab what shows with the inventory open, and Other what shows elsewhere, such as the Esc menu."))), (RectTransform)null);
				Ui.Place(_modes.Root, 0f, 0.5f, 204f, 0f, _modes.Width, 28f);
				_modeShown = -1;
			}
			if (editor._modeSw != null && (Object)(object)editor._modeSw.Root != (Object)null && ((Component)editor._modeSw.Root).gameObject.activeSelf)
			{
				((Component)editor._modeSw.Root).gameObject.SetActive(false);
			}
			ElementMode val = (SeneaLHud.EditorMode = CurrentMode(editor));
			if ((int)val != _modeShown)
			{
				_modeShown = (int)val;
				_modes.SetIdx(_modeShown, false);
				_dirty = true;
			}
			if (editor._open)
			{
				_modes.Tick();
				if (_other)
				{
					SelectInMode(editor, (ElementMode)2);
				}
			}
		}

		private void PickMode(int index)
		{
			HudEditor editor = Editor;
			if (!((Object)(object)editor == (Object)null))
			{
				_other = index == 2;
				editor.SetMode(index == 1);
				if (_other)
				{
					SelectInMode(editor, (ElementMode)2);
				}
				_dirty = true;
			}
		}

		private static void SelectInMode(HudEditor editor, ElementMode mode)
		{
			//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_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			if (editor._sel >= 0 && editor._sel < editor._targets.Length && editor._targets[editor._sel] is ElementTarget elementTarget && elementTarget.Mode == mode)
			{
				return;
			}
			for (int i = 0; i < editor._targets.Length; i++)
			{
				if (editor._targets[i] is ElementTarget elementTarget2 && elementTarget2.Mode == mode && ((EditTarget)elementTarget2).Present)
				{
					editor.Select(i);
					break;
				}
			}
		}

		private void HideForOther()
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Invalid comparison between Unknown and I4
			HudEditor editor = Editor;
			if (!_other || (Object)(object)editor == (Object)null || !editor._open || editor._frames == null || editor._targets == null)
			{
				return;
			}
			for (int i = 0; i < editor._targets.Length && i < editor._frames.Length; i++)
			{
				if (editor._targets[i] is ElementTarget elementTarget && (int)elementTarget.Mode == 2)
				{
					continue;
				}
				if ((Object)(object)editor._frames[i] != (Object)null && ((Component)editor._frames[i]).gameObject.activeSelf)
				{
					((Component)editor._frames[i]).gameObject.SetActive(false);
					editor._can[i] = false;
				}
				if (editor._handles == null || i >= editor._handles.Length || editor._handles[i] == null)
				{
					continue;
				}
				RectTransform[] array = editor._handles[i];
				foreach (RectTransform val in array)
				{
					if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeSelf)
					{
						((Component)val).gameObject.SetActive(false);
					}
				}
			}
		}

		private void KeepListsInMode()
		{
			HudEditor editor = Editor;
			if (_broken || (Object)(object)editor == (Object)null || !editor._open || editor._targets == null)
			{
				return;
			}
			object obj = InspectorField?.GetValue(editor);
			if (obj == null)
			{
				return;
			}
			try
			{
				if (InspectorMap?.GetValue(obj) is List<int> list)
				{
					list.RemoveAll((int i) => i < 0 || i >= editor._targets.Length || !InMode(editor, editor._targets[i]));
				}
				if (!(AttachCandidates != null) || !(InspectorOptions?.GetValue(obj) is List<EditOption> list2))
				{
					return;
				}
				foreach (EditOption item in list2)
				{
					if (item.Names?.Method.Name == "AttachNames")
					{
						AttachInMode(editor, item);
					}
				}
			}
			catch (Exception arg)
			{
				_broken = true;
				_log.LogWarning((object)$"The HUD editor additions stopped after an error and stay off until the game restarts; SeneaL UI's editor is unaffected: {arg}");
			}
		}

		private void AttachInMode(HudEditor editor, EditOption option)
		{
			Func<string[]> names = option.Names;
			Func<int> get = option.GetI;
			Action<int> set = option.SetI;
			List<int> kept = new List<int>();
			option.Names = delegate
			{
				string[] all = names();
				Gather();
				return kept.Select((int i) => all[i]).ToArray();
			};
			option.GetI = delegate
			{
				Gather();
				int num = kept.IndexOf(get());
				return (num >= 0) ? num : 0;
			};
			option.SetI = delegate(int shown)
			{
				Gather();
				set((shown >= 0 && shown < kept.Count) ? kept[shown] : 0);
			};
			void Gather()
			{
				string[] array = names();
				IList list = AttachCandidates.GetValue(null) as IList;
				int num = array.Length - (list?.Count ?? 0);
				kept.Clear();
				for (int i = 0; i < array.Length; i++)
				{
					if (i >= num)
					{
						object? obj = list?[i - num];
						EditTarget val = (EditTarget)((obj is EditTarget) ? obj : null);
						if (val != null && !InMode(editor, val))
						{
							continue;
						}
					}
					kept.Add(i);
				}
			}
		}

		private bool InMode(HudEditor editor, EditTarget target)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Invalid comparison between Unknown and I4
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_0028: Invalid comparison between Unknown and I4
			ElementMode val = CurrentMode(editor);
			if (target is ElementTarget elementTarget)
			{
				return elementTarget.Mode == val;
			}
			if ((int)val != 2)
			{
				return target.IsTab == ((int)val == 1);
			}
			return false;
		}

		private void BuildButton(HudEditor editor)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Expected O, but got Unknown
			//IL_0080: 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_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Expected O, but got Unknown
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0148: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			_bar = editor._bar;
			_button = new Tb((Transform)(object)editor._bar, "unlocker.elements", "search", (Action)delegate
			{
				_panelOpen.Value = !_panelOpen.Value;
				_dirty = true;
			}, (Func<Tip>)(() => Tips.Text(new Tip(), Lang.T("EditorAdditions.ElementsTitle", "Elements"), Lang.T("EditorAdditions.ElementsTip", "Open or close the list of every element, with search, show, lock, lining up and spacing."))), (Action)null);
			_button.SetLabel((string)null);
			RectTransform val = ((editor._othersBtn == null) ? null : editor._othersBtn.Root);
			float num = (((Object)(object)val == (Object)null) ? 478f : (val.anchoredPosition.x + 44f));
			Ui.Place(_button.Root, 0f, 0.5f, num, 0f, _button.Width, 36f);
			float num2 = num + _button.Width + 6f;
			float x = _bar.sizeDelta.x;
			float num3 = x;
			foreach (RectTransform item in (Transform)_bar)
			{
				RectTransform val2 = item;
				if ((Object)(object)val2 != (Object)(object)_button.Root && val2.anchorMin.x >= 1f && ((Component)val2).gameObject.activeSelf)
				{
					num3 = Mathf.Min(num3, x + val2.anchoredPosition.x - val2.sizeDelta.x * val2.pivot.x);
				}
			}
			if (num3 < num2)
			{
				_bar.sizeDelta = new Vector2(x + num2 - num3, _bar.sizeDelta.y);
			}
		}

		private void BuildPanel(HudEditor editor)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_010f: 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_012d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			//IL_0161: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ab: 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_025d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0263: Expected O, but got Unknown
			//IL_02b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bb: Expected O, but got Unknown
			//IL_034d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0357: Expected O, but got Unknown
			//IL_03d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_03dc: Expected O, but got Unknown
			_canvas = new GameObject("SeneaLUIUnlocker_EditorPanel", new Type[4]
			{
				typeof(RectTransform),
				typeof(Canvas),
				typeof(CanvasScaler),
				typeof(GraphicRaycaster)
			});
			Object.DontDestroyOnLoad((Object)(object)_canvas);
			Canvas component = _canvas.GetComponent<Canvas>();
			component.renderMode = (RenderMode)0;
			Canvas component2 = ((Component)editor).GetComponent<Canvas>();
			component.sortingOrder = (((Object)(object)component2 == (Object)null) ? 30500 : component2.sortingOrder) + 1;
			CanvasScaler component3 = _canvas.GetComponent<CanvasScaler>();
			component3.uiScaleMode = (ScaleMode)0;
			component3.scaleFactor = 1f;
			CanvasScaler component4 = ((Component)editor).GetComponent<CanvasScaler>();
			component3.referencePixelsPerUnit = (((Object)(object)component4 == (Object)null) ? SkinScale.Ppu : component4.referencePixelsPerUnit);
			_panel = Ui.Node(_canvas.transform, "panel");
			RectTransform panel = _panel;
			RectTransform panel2 = _panel;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0f, 1f);
			panel2.anchorMax = val;
			panel.anchorMin = val;
			_panel.pivot = new Vector2(0f, 1f);
			_panel.anchoredPosition = new Vector2(24f, -120f);
			_panel.sizeDelta = new Vector2(300f, 600f);
			((Graphic)Ui.Panel(_panel, Skin.Sliced(48, Styles.Glass78, -1), Styles.Glass78, false)).raycastTarget = true;
			DragSurface obj = ((Component)_panel).gameObject.AddComponent<DragSurface>();
			Vector2 from = Vector2.zero;
			Vector2 start = Vector2.zero;
			obj.OnDown = delegate(Vector2 p)
			{
				//IL_0001: Unknown result type (might be due to invalid IL or missing references)
				//IL_0002: Unknown result type (might be due to invalid IL or missing references)
				//IL_0013: Unknown result type (might be due to invalid IL or missing references)
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				from = p;
				start = _panel.anchoredPosition;
			};
			obj.OnMove = delegate(Vector2 p)
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_001f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0024: Unknown result type (might be due to invalid IL or missing references)
				//IL_0029: Unknown result type (might be due to invalid IL or missing references)
				_panelMoved = true;
				_panel.anchoredPosition = start + (p - from);
			};
			TextMeshProUGUI obj2 = Ui.Label((Transform)(object)_panel, "title", TextStyles.PanelTitle, 0f, 12f, 26f, 276f, (TextAlignmentOptions)513);
			((TMP_Text)obj2).text = Lang.T("ElementsPanel.Title", "Elements");
			((Graphic)obj2).raycastTarget = false;
			Tb val2 = new Tb((Transform)(object)_panel, "copy", "layers", (Action)delegate
			{
				CopyLook(Editor);
			}, (Func<Tip>)(() => Tips.Text(new Tip(), Lang.T("Look.CopyLook", "Copy Look"), Lang.T("Look.CopyLookTip", "Copy the selected element's look: size, text size, opacity, transparency, background, colors, style, value position, key cap, caption look and animation."))), (Action)null);
			val2.SetLabel(Lang.T("ElementsPanel.Copy", "Copy"));
			Tb val3 = new Tb((Transform)(object)_panel, "paste", "grab", (Action)delegate
			{
				PasteLook(Editor);
			}, (Func<Tip>)(() => Tips.Text(new Tip(), Lang.T("Look.PasteLook", "Paste Look"), Lang.T("Look.PasteLookTip", "Give the selected element the look last copied; its place, attachment and content stay as they are."))), (Action)null);
			val3.SetLabel(Lang.T("ElementsPanel.Paste", "Paste"));
			Ui.Place(val3.Root, 1f, 1f, -12f, -4f, val3.Width, 36f);
			Ui.Place(val2.Root, 1f, 1f, -12f - val3.Width - 6f, -4f, val2.Width, 36f);
			_search = new SearchBox((Transform)(object)_panel, "search", 276f, "search");
			Ui.Place(_search.Root, 0f, 1f, 12f, -42f, 276f, 32f);
			_search.SetPlaceholder(Lang.T("ElementsPanel.Search", "Search"));
			_search.Changed += delegate(string text)
			{
				_filter = (text ?? "").Trim().ToLowerInvariant();
				_dirty = true;
			};
			_scroll = new ScrollBox((Transform)(object)_panel, "rows", 276f, 508f, 96f);
			_fitted = -1f;
			_dirty = true;
		}

		private void Fit(HudEditor editor)
		{
			//IL_0018: 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_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_020e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0236: Unknown result type (might be due to invalid IL or missing references)
			//IL_023b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_0358: Unknown result type (might be due to invalid IL or missing references)
			//IL_035d: Unknown result type (might be due to invalid IL or missing references)
			//IL_036c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Expected O, but got Unknown
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_0291: Unknown result type (might be due to invalid IL or missing references)
			//IL_02dc: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(0.3f, ((Transform)editor._host).lossyScale.x);
			if (!Mathf.Approximately(((Transform)_panel).localScale.x, num))
			{
				((Transform)_panel).localScale = Vector3.one * num;
			}
			float num2 = Mathf.Clamp((float)Screen.height / num - 40f, 260f, 600f);
			if (!Mathf.Approximately(num2, _fitted))
			{
				_fitted = num2;
				_panel.sizeDelta = new Vector2(300f, num2);
				float num3 = 80f;
				_alignShown = _picked.Count >= 2;
				if (_alignShown && _align == null)
				{
					_align = new ElementSelect(_panel, 12f, 0f, 276f, _panel);
					_align.BindNames(AlignNames, -1);
					_align.SetCurrent(Lang.T("EditorAdditions.LineUp", "Line Up Picked Elements"));
					_align.OnPick = delegate(int i)
					{
						Arrange(Editor, i);
						_align.SetCurrent(Lang.T("EditorAdditions.LineUp", "Line Up Picked Elements"));
					};
				}
				if (_align != null)
				{
					((Component)_align._root).gameObject.SetActive(_alignShown);
					if (!_alignShown)
					{
						_align.Close();
					}
					_align._root.anchoredPosition = new Vector2(12f, 0f - num3);
				}
				if (_alignShown)
				{
					num3 += 42f;
				}
				_scroll.Place(12f, num3, 276f, num2 - num3 - 12f, 8f);
			}
			float w = 300f * num;
			float h = num2 * num;
			Vector2 anchoredPosition = _panel.anchoredPosition;
			Vector2 clamped = new Vector2(Mathf.Clamp(anchoredPosition.x, 0f, Mathf.Max(0f, (float)Screen.width - w)), Mathf.Clamp(anchoredPosition.y, 0f - Mathf.Max(0f, (float)Screen.height - h), 0f));
			List<Rect> avoid;
			if (!_panelMoved)
			{
				avoid = new List<Rect>(2);
				RectTransform val = ((editor._insp == null) ? null : editor._insp.Root);
				if ((Object)(object)val != (Object)null && ((Component)val).gameObject.activeInHierarchy)
				{
					avoid.Add(ScreenRect(val));
				}
				if (editor._sel >= 0 && editor._sel < editor._targets.Length && editor._targets[editor._sel].Editable)
				{
					avoid.Add(editor._targets[editor._sel].Frame());
				}
				float num4 = 24f;
				float num5 = Mathf.Max(0f, (float)Screen.width - w - 24f);
				if (!Clear(clamped.x))
				{
					clamped.x = (Clear(num4) ? num4 : (Clear(num5) ? num5 : clamped.x));
				}
			}
			if (clamped != anchoredPosition)
			{
				_panel.anchoredPosition = clamped;
			}
			bool Clear(float x)
			{
				return !avoid.Exists((Rect r) => ((Rect)(ref r)).width > 0f && ((Rect)(ref r)).Overlaps(new Rect(x, (float)Screen.height + clamped.y - h, w, h)));
			}
		}

		private static Rect ScreenRect(RectTransform rect)
		{
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			Vector3[] array = (Vector3[])(object)new Vector3[4];
			rect.GetWorldCorners(array);
			return Rect.MinMaxRect(array[0].x, array[0].y, array[2].x, array[2].y);
		}

		private void Rebuild(HudEditor editor)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_0159: Unknown result type (might be due to invalid IL or missing references)
			_dirty = false;
			foreach (Row row2 in _rows)
			{
				Object.Destroy((Object)(object)((Component)row2.Root).gameObject);
			}
			_rows.Clear();
			_listedMode = CurrentMode(editor);
			float num = 0f;
			for (int i = 0; i < editor._targets.Length; i++)
			{
				EditTarget val = editor._targets[i];
				if (!val.Present || !val.Available || !InMode(editor, val))
				{
					continue;
				}
				bool?[] array = ((val.E == null || !(val.E.Key == "Crafting") || CraftingPlacement.Current == null || !CraftingPlacement.Current.Enabled) ? new bool?[1] : new bool?[2] { false, true });
				foreach (bool? station in array)
				{
					string text = Row.Title(val, station);
					if (_filter.Length <= 0 || text.ToLowerInvariant().Contains(_filter))
					{
						Row row = new Row(this, _scroll.Content, i, station, 264f);
						row.Root.anchoredPosition = new Vector2(0f, 0f - num);
						num += 28f;
						_rows.Add(row);
					}
				}
			}
			_scroll.SetContentHeight(num);
		}

		private bool Locked(EditTarget t)
		{
			return LockedKeys().Contains(t.E.Key);
		}

		private HashSet<string> LockedKeys()
		{
			return (from k in _locked.Value.Split(new char[1] { ';' })
				select k.Trim() into k
				where k.Length > 0
				select k).ToHashSet();
		}

		private void ToggleLock(EditTarget t)
		{
			HashSet<string> hashSet = LockedKeys();
			if (!hashSet.Remove(t.E.Key))
			{
				hashSet.Add(t.E.Key);
			}
			_locked.Value = string.Join("; ", hashSet.OrderBy((string k) => k));
		}

		private void Hold(HudEditor editor, int i, bool locked)
		{
			List<RectTransform> list = new List<RectTransform> { editor._frames[i] };
			if (editor._handles != null && i < editor._handles.Length && editor._handles[i] != null)
			{
				list.AddRange(editor._handles[i]);
			}
			foreach (RectTransform item in list.Where((RectTransform r) => (Object)(object)r != (Object)null))
			{
				DragSurface component = ((Component)item).GetComponent<DragSurface>();
				if ((Object)(object)component == (Object)null)
				{
					continue;
				}
				(Action<Vector2>, Action<Vector2>, Action) value;
				if (locked && !_original.ContainsKey(item))
				{
					_original[item] = (component.OnDown, component.OnMove, component.OnUp);
					int index = i;
					component.OnDown = delegate
					{
						editor.Select(index);
					};
					component.OnMove = null;
					component.OnUp = null;
				}
				else if (!locked && _original.TryGetValue(item, out value))
				{
					(component.OnDown, component.OnMove, component.OnUp) = value;
					_original.Remove(item);
				}
			}
		}

		private static ConfigEntryBase[] Place(Elem e)
		{
			return ((IEnumerable<ConfigEntryBase>)(object)new ConfigEntryBase[5]
			{
				(ConfigEntryBase)e.PosX,
				(ConfigEntryBase)e.PosY,
				(ConfigEntryBase)e.Size,
				(ConfigEntryBase)e.GlueX,
				(ConfigEntryBase)e.GlueY
			}).Where((ConfigEntryBase entry) => entry != null).ToArray();
		}

		private void HookInspector(HudEditor editor)
		{
			//IL_0092: 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_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			RectTransform root = ((editor._insp == null) ? null : editor._insp.Root);
			if (!((Object)(object)root == (Object)null) && !((Object)(object)root == (Object)(object)_inspHooked))
			{
				_inspHooked = root;
				if ((Object)(object)((Component)root).GetComponent<Graphic>() == (Object)null)
				{
					((Graphic)Ui.Img(root, (Sprite)null, Palette.Clear)).raycastTarget = true;
				}
				DragSurface obj = ((Component)root).gameObject.AddComponent<DragSurface>();
				Vector2 from = Vector2.zero;
				Vector2 start = Vector2.zero;
				obj.OnDown = delegate(Vector2 p)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					//IL_0002: Unknown result type (might be due to invalid IL or missing references)
					//IL_000e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0013: Unknown result type (might be due to invalid IL or missing references)
					from = p;
					start = root.anchoredPosition;
				};
				obj.OnMove = delegate(Vector2 p)
				{
					//IL_0013: Unknown result type (might be due to invalid IL or missing references)
					//IL_0018: Unknown result type (might be due to invalid IL or missing references)
					//IL_001a: Unknown result type (might be due to invalid IL or missing references)
					//IL_001f: Unknown result type (might be due to invalid IL or missing references)
					//IL_002f: Unknown result type (might be due to invalid IL or missing references)
					//IL_003e: Unknown result type (might be due to invalid IL or missing references)
					//IL_0043: Unknown result type (might be due to invalid IL or missing references)
					//IL_0048: Unknown result type (might be due to invalid IL or missing references)
					_inspMoved = true;
					_inspAt = start + (p - from) / Mathf.Max(0.01f, ((Transform)root).lossyScale.x);
				};
			}
		}

		private static void Toast(HudEditor editor, string text)
		{
			if (!((Object)(object)editor == (Object)null))
			{
				editor.SetHint(text);
				editor._toastUntil = Time.unscaledTime + 3.5f;
			}
		}

		private static Elem Selected(HudEditor editor)
		{
			if (!((Object)(object)editor == (Object)null) && editor._targets != null && editor._sel >= 0 && editor._sel < editor._targets.Length)
			{
				return editor._targets[editor._sel].E;
			}
			return null;
		}

		private void CopyLook(HudEditor editor)
		{
			Elem val = Selected(editor);
			if (val == null)
			{
				Toast(editor, Lang.T("EditorAdditions.SelectToCopy", "Select an element to copy its look"));
				return;
			}
			_look = new Dictionary<string, object>();
			_lookFrom = editor._targets[editor._sel].Name;
			string[] lookFields = LookFields;
			foreach (string text in lookFields)
			{
				object? obj = AccessTools.Field(typeof(Elem), text)?.GetValue(val);
				ConfigEntryBase val2 = (ConfigEntryBase)((obj is ConfigEntryBase) ? obj : null);
				if (val2 != null)
				{
					_look[text] = val2.BoxedValue;
				}
			}
			Toast(editor, Lang.F("EditorAdditions.Copied", "Copied the look of {0}", new object[1] { _lookFrom }));
		}

		private void PasteLook(HudEditor editor)
		{
			Elem val = Selected(editor);
			if (val == null || _look == null)
			{
				Toast(editor, (_look == null) ? Lang.T("EditorAdditions.CopyFirst", "Copy an element's look first") : Lang.T("EditorAdditions.SelectToPaste", "Select an element to paste the look onto"));
				return;
			}
			foreach (KeyValuePair<string, object> item in _look)
			{
				object? obj = AccessTools.Field(typeof(Elem), item.Key)?.GetValue(val);
				ConfigEntryBase val2 = (ConfigEntryBase)((obj is ConfigEntryBase) ? obj : null);
				if (val2 != null)
				{
					val2.BoxedValue = item.Value;
				}
			}
			Toast(editor, Lang.F("EditorAdditions.Gave", "Gave {0} the look of {1}", new object[2]
			{
				editor._targets[editor._sel].Name,
				_lookFrom
			}));
		}

		private void ClearElementsPanel(RectTransform root)
		{
			//IL_00b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: 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_00f5: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_panel == (Object)null) && ((Component)_panel).gameObject.activeInHierarchy)
			{
				Vector3[] array = (Vector3[])(object)new Vector3[4];
				root.GetWorldCorners(array);
				Vector3[] array2 = (Vector3[])(object)new Vector3[4];
				_panel.GetWorldCorners(array2);
				if (array[0].x < array2[2].x && array[2].x > array2[0].x && array[0].y < array2[2].y && array[2].y > array2[0].y)
				{
					root.anchoredPosition += new Vector2((array2[2].x + 12f - array[0].x) / Mathf.Max(0.01f, ((Transform)root).lossyScale.x), 0f);
				}
			}
		}

		private void PlaceInspector()
		{
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_0101: 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_01c8: 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_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01eb: Unknown result type (might be due to invalid IL or missing references)
			HudEditor editor = Editor;
			RectTransform inspHooked = _inspHooked;
			if ((Object)(object)inspHooked == (Object)null || (Object)(object)editor == (Object)null || editor._insp == null || (Object)(object)editor._insp.Root != (Object)(object)inspHooked || !((Component)inspHooked).gameObject.activeInHierarchy)
			{
				return;
			}
			if (!_inspMoved)
			{
				ClearElementsPanel(inspHooked);
				return;
			}
			inspHooked.anchoredPosition = _inspAt;
			Transform parent = ((Transform)inspHooked).parent;
			RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			if (!((Object)(object)val == (Object)null))
			{
				Vector3[] array = (Vector3[])(object)new Vector3[4];
				inspHooked.GetWorldCorners(array);
				Vector3[] array2 = (Vector3[])(object)new Vector3[4];
				val.GetWorldCorners(array2);
				float num = Mathf.Max(0.01f, ((Transform)inspHooked).lossyScale.x);
				Vector2 zero = Vector2.zero;
				if (array[2].x > array2[2].x)
				{
					zero.x = (array2[2].x - array[2].x) / num;
				}
				if (array[0].x + zero.x * num < array2[0].x)
				{
					zero.x = (array2[0].x - array[0].x) / num;
				}
				if (array[2].y > array2[2].y)
				{
					zero.y = (array2[2].y - array[2].y) / num;
				}
				if (array[0].y + zero.y * num < array2[0].y)
				{
					zero.y = (array2[0].y - array[0].y) / num;
				}
				if (zero != Vector2.zero)
				{
					_inspAt += zero;
					inspHooked.anchoredPosition = _inspAt;
				}
			}
		}

		private void ShowSample(HudEditor editor)
		{
			int sel = editor._sel;
			if (sel != _seenSel)
			{
				_seenSel = sel;
				if (_demoOn != null)
				{
					HudEditor.SetDemo(_demoOn, false);
					_demoOn = null;
				}
				if (sel >= 0 && sel < editor._targets.Length && !HudEditor.Demo(editor._targets[sel].E))
				{
					_demoOn = editor._targets[sel].E;
					HudEditor.SetDemo(_demoOn, true);
				}
			}
		}

		private void KeepPlace(Elem e)
		{
			string[] array = (from entry in Place(e)
				select entry.GetSerializedValue()).ToArray();
			if (!_lockedPlace.TryGetValue(e.Key, out var value))
			{
				_lockedPlace[e.Key] = array;
			}
			else if (!array.SequenceEqual(value))
			{
				ConfigEntryBase[] array2 = Place(e);
				for (int num = 0; num < array2.Length; num++)
				{
					array2[num].SetSerializedValue(value[num]);
				}
			}
		}

		private void ExtendObjects(HudEditor editor)
		{
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Expected O, but got Unknown
			//IL_00cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected O, but got Unknown
			object value = ObjectsField.GetValue(editor);
			if (value == null || !(bool)ObjectsOpen.GetValue(value))
			{
				return;
			}
			RectTransform val = (RectTransform)ObjectsPop.GetValue(value);
			List<GameObject> list = (List<GameObject>)ObjectsRows.GetValue(value);
			List<int> list2 = (List<int>)ObjectsList.GetValue(value);
			if ((Object)(object)val == (Object)null || list == null || list2 == null || list.Count != list2.Count)
			{
				return;
			}
			for (int i = 0; i < list.Count; i++)
			{
				GameObject val2 = list[i];
				if ((Object)(object)val2 == (Object)null || list2[i] < 0 || list2[i] >= editor._targets.Length)
				{
					continue;
				}
				if (!_objectRows.TryGetValue(val2, out (int, Tb, Tb, Tb) value2))
				{
					value2 = AddRowTools(editor, (RectTransform)val2.transform, list2[i]);
					_objectRows[val2] = value2;
				}
				EditTarget val3 = editor._targets[value2.Item1];
				if (val3.E != null)
				{
					Tb item = value2.Item2;
					if (item != null)
					{
						item.SetLit(Locked(val3));
					}
					Tb item2 = value2.Item3;
					if (item2 != null)
					{
						item2.SetLit(Picked(val3));
					}
				}
				Tb item3 = value2.Item4;
				if (item3 != null)
				{
					item3.SetLit(CraftingPlacement.Current != null && CraftingPlacement.Current.EditingStation);
				}
			}
			foreach (GameObject item4 in _objectRows.Keys.Where((GameObject r) => (Object)(object)r == (Object)null).ToList())
			{
				_objectRows.Remove(item4);
			}
			ExtendFooter(val, (list.Count != 0) ? ((Object)list[0]).GetInstanceID() : 0, list.Count);
		}

		private (int Index, Tb Lock, Tb Pick, Tb Station) AddRowTools(HudEditor editor, RectTransform row, int index)
		{
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Expected O, but got Unknown
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_023d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_0276: Unknown result type (might be due to invalid IL or missing references)
			//IL_028a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0294: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c1: Expected O, but got Unknown
			EditTarget val = editor._targets[index];
			if (val.E == null || !val.Available || !val.Present)
			{
				return (Index: index, Lock: null, Pick: null, Station: null);
			}
			float y = row.sizeDelta.y;
			Tb val2 = new Tb((Transform)(object)row, "unlocker.lock", "lock", (Action)delegate
			{
				ToggleLock(Editor._targets[index]);
			}, (Func<Tip>)(() => Tips.Text(new Tip(), Lang.T("EditorAdditions.Lock", "Lock"), Lang.T("EditorAdditions.LockTip", "Lock this element in place: it can still be selected and set, but not moved."))), (Action)null);
			val2.SetLabel((string)null);
			Ui.Place(val2.Root, 1f, 1f, -34f, (0f - (y - 26f)) * 0.5f, 26f, 26f);
			Tb val3 = new Tb((Transform)(object)row, "unlocker.pick", "check", (Action)delegate
			{
				TogglePick(Editor._targets[index]);
			}, (Func<Tip>)(() => Tips.Text(new Tip(), Lang.T("EditorAdditions.Pick", "Pick"), Lang.T("EditorAdditions.PickTip", "Pick this element to line it up or space it evenly with the other picked elements."))), (Action)null);
			val3.SetLabel((string)null);
			Ui.Place(val3.Root, 1f, 1f, -64f, (0f - (y - 26f)) * 0.5f, 26f, 26f);
			float num = 60f;
			Tb val4 = null;
			if (val.E.Key == "Crafting" && CraftingPlacement.Current != null && CraftingPlacement.Current.Enabled)
			{
				val4 = new Tb((Transform)(object)row, "unlocker.station", "layers", (Action)delegate
				{
					CraftingPlacement current = CraftingPlacement.Current;
					if (current != null)
					{
						current.Edit(!current.EditingStation);
					}
					Editor.Select(index);
				}, (Func<Tip>)(() => Tips.Text(new Tip(), Lang.T("ObjectsList.StationPlacement", "Station Placement"), Lang.T("ObjectsList.StationPlacementTip", "Switch between placing the Crafting window beside your inventory and at a crafting station, where SeneaL UI draws it wider; lit while the station placement is the one being set."))), (Action)null);
				val4.SetLabel((string)null);
				Ui.Place(val4.Root, 1f, 1f, -94f, (0f - (y - 26f)) * 0.5f, 26f, 26f);
				num = 90f;
			}
			Transform obj = ((Transform)row).Find("t");
			RectTransform val5 = (RectTransform)(object)((obj is RectTransform) ? obj : null);
			if ((Object)(object)val5 != (Object)null)
			{
				val5.sizeDelta = new Vector2(Mathf.Max(60f, val5.sizeDelta.x - num), val5.sizeDelta.y);
			}
			Transform obj2 = ((Transform)row).Find("n");
			RectTransform val6 = (RectTransform)(object)((obj2 is RectTransform) ? obj2 : null);
			if ((Object)(object)val6 != (Object)null)
			{
				val6.sizeDelta = new Vector2(Mathf.Max(60f, val6.sizeDelta.x - num), val6.sizeDelta.y);
			}
			return (Index: index, Lock: val2, Pick: val3, Station: val4);
		}

		private void ExtendFooter(RectTransform pop, int firstRow, int rowCount)
		{
			//IL_0077: 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_00d6: 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_0100: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_toolsPop != (Object)(object)pop || (Object)(object)_objectsTools == (Object)null)
			{
				BuildFooter(pop);
			}
			bool flag = _picked.Count >= 2;
			bool num = firstRow != _firstRow || rowCount != _rowCount;
			_firstRow = firstRow;
			_rowCount = rowCount;
			if (num || !Mathf.Approximately(pop.sizeDelta.y, _popSet))
			{
				_listHeight = pop.sizeDelta.y;
				_arrangeShown = !flag;
			}
			else if (flag == _arrangeShown)
			{
				return;
			}
			_arrangeShown = flag;
			((Component)_arrangeGrid).gameObject.SetActive(flag);
			float num2 = 42f + (flag ? 126f : 0f);
			_objectsTools.sizeDelta = new Vector2(340f, num2);
			_popSet = _listHeight + num2;
			pop.sizeDelta = new Vector2(pop.sizeDelta.x, _popSet);
		}

		private void BuildFooter(RectTransform pop)
		{
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: 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_007d: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Expected O, but got Unknown
			//IL_0134: Unknown result type (might be due to invalid IL or missing references)
			//IL_013a: Expected O, but got Unknown
			//IL_01df: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0215: Unknown result type (might be due to invalid IL or missing references)
			//IL_022f: Unknown result type (might be due to invalid IL or missing references)
			//IL_02aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_02af: Unknown result type (might be due to invalid IL or missing references)
			_toolsPop = pop;
			_popSet = -1f;
			_arrangeShown = false;
			_objectsTools = Ui.Node((Transform)(object)pop, "unlocker.tools");
			RectTransform objectsTools = _objectsTools;
			RectTransform objectsTools2 = _objectsTools;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0f, 0f);
			objectsTools2.anchorMax = val;
			objectsTools.anchorMin = val;
			_objectsTools.pivot = new Vector2(0f, 0f);
			_objectsTools.anchoredPosition = new Vector2(10f, 10f);
			_objectsTools.sizeDelta = new Vector2(340f, 36f);
			Tb val2 = new Tb((Transform)(object)_objectsTools, "copy", "layers", (Action)delegate
			{
				CopyLook(Editor);
			}, (Func<Tip>)(() => Tips.Text(new Tip(), Lang.T("Look.CopyLook", "Copy Look"), Lang.T("Look.CopyLookTip", "Copy the selected element's look: size, text size, opacity, transparency, background, colors, style, value position, key cap, caption look and animation."))), (Action)null);
			val2.SetLabel(Lang.T("Look.CopyLook", "Copy Look"));
			Tb val3 = new Tb((Transform)(object)_objectsTools, "paste", "grab", (Action)delegate
			{
				PasteLook(Editor);
			}, (Func<Tip>)(() => Tips.Text(new Tip(), Lang.T("Look.PasteLook", "Paste Look"), Lang.T("Look.PasteLookTip", "Give the selected element the look last copied; its place, attachment and content stay as they are."))), (Action)null);
			val3.SetLabel(Lang.T("Look.PasteLook", "Paste Look"));
			Ui.Place(val2.Root, 0f, 0f, 0f, 0f, val2.Width, 36f);
			Ui.Place(val3.Root, 0f, 0f, val2.Width + 6f, 0f, val3.Width, 36f);
			_arrangeGrid = Ui.Node((Transform)(object)_objectsTools, "arrange");
			RectTransform arrangeGrid = _arrangeGrid;
			RectTransform arrangeGrid2 = _arrangeGrid;
			((Vector2)(ref val))..ctor(0f, 0f);
			arrangeGrid2.anchorMax = val;
			arrangeGrid.anchorMin = val;
			_arrangeGrid.pivot = new Vector2(0f, 0f);
			_arrangeGrid.anchoredPosition = new Vector2(0f, 42f);
			_arrangeGrid.sizeDelta = new Vector2(340f, 120f);
			for (int num = 0; num < ArrangeLabels.Length; num++)
			{
				int how = num;
				string tip = ArrangeTips[num];
				string label = ArrangeLabels[num];
				Tb val4 = new Tb((Transform)(object)_arrangeGrid, "arrange" + num, "check", (Action)delegate
				{
					Arrange(Editor, how);
				}, (Func<Tip>)(() => Tips.Text(new Tip(), label, tip)), (Action)null);
				val4.SetLabel(label);
				int num2 = num % 3;
				int num3 = 2 - num / 3;
				Ui.Place(val4.Root, 0f, 0f, (float)num2 * 114f, (float)num3 * 42f, 108f, 36f);
			}
			((Component)_arrangeGrid).gameObject.SetActive(false);
		}
	}
	internal sealed class ElementLooks : IElementLooks
	{
		private sealed class Mirror
		{
			public ConfigEntryBase Entry;

			public string Last;
		}

		private sealed class State
		{
			public readonly BackdropSync Backdrop = new BackdropSync();

			public ElemCaption Caption;

			public RectTransform CaptionSpace;

			public readonly Dictionary<TMP_Text, float> BaseSizes = new Dictionary<TMP_Text, float>();

			public float Scale = 1f;

			public float NextTextCheck;
		}

		private const float TextCheckSeconds = 0.5f;

		private const float KeepSeconds = 1f;

		private const float MirrorSeconds = 0.2f;

		private static readonly FieldInfo[] Settings = (from field in typeof(Elem).GetFields(BindingFlags.Instance | BindingFlags.Public)
			where typeof(ConfigEntryBase).IsAssignableFrom(field.FieldType)
			select field).ToArray();

		private static readonly ConfigFile Unsaved;

		private readonly Dictionary<string, State> _states = new Dictionary<string, State>();

		private readonly HashSet<string> _restored = new HashSet<string>(StringComparer.Ordinal);

		private Dictionary<string, string> _kept;

		private float _nextKeep;

		private float _nextMirror;

		private readonly Dictionary<ConfigEntryBase, Mirror> _mirrors = new Dictionary<ConfigEntryBase, Mirror>();

		private static readonly MethodInfo BindDefinition;

		private string _activePath;

		private DateTime _activeWritten;

		private HashSet<string> _activeKeys;

		public static IElementLooks Create()
		{
			_ = ExtElements.Elems;
			return (IElementLooks)(object)new ElementLooks();
		}

		private static Elem Elem(string id)
		{
			if (!ExtElements.Elems.TryGetValue("x.alkeari.valheim.senealuiunlocker." + id, out var value))
			{
				return null;
			}
			return value;
		}

		public float TextScale(string id)
		{
			Elem val = Elem(id);
			if (val != null && val.TextK != null)
			{
				return val.TextK.Value;
			}
			return 1f;
		}

		public void Tick(ICollection<string> selfScaled)
		{
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			foreach (var (text, val) in SeneaLHud.Registrations)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				Elem val2 = Elem(text);
				if (val2 != null)
				{
					if (_restored.Add(text))
					{
						Restore(val2);
					}
					if (!_states.TryGetValue(text, out var value))
					{
						value = (_states[text] = new State());
					}
					RectTransform val3 = SeneaLHud.LookRootOf(text, val);
					value.Backdrop.Tick(val2, (Transform)(object)val3);
					Transform root = ((Transform)val).root;
					RectTransform val4 = (RectTransform)(object)((root is RectTransform) ? root : null);
					if (value.Caption == null || (Object)(object)value.CaptionSpace != (Object)(object)val4)
					{
						value.CaptionSpace = val4;
						value.Caption = (((Object)(object)val4 == (Object)null) ? ((ElemCaption)null) : new ElemCaption(val2, val4));
					}
					ElemCaption caption = value.Caption;
					if (caption != null)
					{
						caption.Tick((((Component)val).gameObject.activeInHierarchy && val2.LiveFrame != null) ? val2.LiveFrame() : Rect.zero, (Camera)null);
					}
					if (!selfScaled.Contains(text))
					{
						ScaleText(val3, value, (val2.TextK == null) ? 1f : val2.TextK.Value);
					}
				}
			}
			if (Time.unscaledTime >= _nextMirror)
			{
				_nextMirror = Time.unscaledTime + 0.2f;
				SyncMirrors();
			}
			if (Time.unscaledTime >= _nextKeep)
			{
				_nextKeep = Time.unscaledTime + 1f;
				Keep();
			}
		}

		public void Tip(RectTransform rect, string title, string body)
		{
			Tooltip.Bind(rect, (Func<Tip>)(() => Tips.Text(new Tip(), title, body)), (RectTransform)null);
		}

		public void SetGrow(string id, int grow)
		{
			Elem val = Elem(id);
			if (val?.Grow != null)
			{
				_restored.Add(id);
				val.Grow.Value = grow;
				Keep();
			}
		}

		public void SetLooks(IReadOnlyDictionary<string, string> looks)
		{
			foreach (var registration in SeneaLHud.Registrations)
			{
				string item = registration.Item1;
				Elem val = Elem(item);
				if (val == null)
				{
					continue;
				}
				_restored.Add(item);
				foreach (ConfigEntryBase item2 in Saved(val))
				{
					if (looks.TryGetValue(item2.Definition.Key, out var value))
					{
						try
						{
							item2.SetSerializedValue(value);
						}
						catch (Exception)
						{
						}
					}
				}
				foreach (ConfigEntryBase item3 in Unkept(val))
				{
					try
					{
						if (looks.TryGetValue(item3.Definition.Key, out var value2))
						{
							item3.SetSerializedValue(value2);
						}
						else
						{
							item3.BoxedValue = item3.DefaultValue;
						}
						if (_mirrors.TryGetValue(item3, out var value3) && value3 != null)
						{
							value3.Entry.SetSerializedValue(item3.GetSerializedValue());
							value3.Last = value3.Entry.GetSerializedValue();
						}
					}
					catch (Exception)
					{
					}
				}
			}
			Keep();
		}

		private void SyncMirrors()
		{
			if (Prefs.Cfg == null || BindDefinition == null)
			{
				return;
			}
			bool saveOnConfigSet = Prefs.Cfg.SaveOnConfigSet;
			bool flag = false;
			Prefs.Cfg.SaveOnConfigSet = false;
			try
			{
				foreach (var registration in SeneaLHud.Registrations)
				{
					string item = registration.Item1;
					Elem val = Elem(item);
					if (val == null || !_restored.Contains(item))
					{
						continue;
					}
					foreach (ConfigEntryBase item2 in Unkept(val))
					{
						if (!_mirrors.TryGetValue(item2, out var value))
						{
							value = (_mirrors[item2] = Bind(item2));
							flag = true;
							if (value == null)
							{
								continue;
							}
						}
						if (value == null)
						{
							continue;
						}
						string serializedValue = value.Entry.GetSerializedValue();
						string serializedValue2 = item2.GetSerializedValue();
						try
						{
							if (serializedValue != value.Last && serializedValue == Default(value.Entry) && !SavedInActive(value.Entry.Definition))
							{
								value.Entry.SetSerializedValue(serializedValue2);
								value.Last = serializedValue2;
								flag = true;
							}
							else if (serializedValue != value.Last)
							{
								item2.SetSerializedValue(serializedValue);
								value.Last = serializedValue;
							}
							else if (serializedValue2 != value.Last)
							{
								value.Entry.SetSerializedValue(serializedValue2);
								value.Last = serializedValue2;
								flag = true;
							}
						}
						catch (Exception)
						{
							value.Last = serializedValue;
						}
					}
				}
			}
			finally
			{
				Prefs.Cfg.SaveOnConfigSet = saveOnConfigSet;
				if (saveOnConfigSet && flag)
				{
					Prefs.Cfg.Save();
				}
			}
		}

		private static string Default(ConfigEntryBase entry)
		{
			return TomlTypeConverter.ConvertToString(entry.DefaultValue, entry.SettingType);
		}

		private bool SavedInActive(ConfigDefinition definition)
		{
			string activeProfile = SeneaLConfig.ActiveProfile;
			string text = ((activeProfile == null) ? null : Path.Combine(Paths.ConfigPath, "SeneaL-UI", "profiles", PresetFix.Safe(activeProfile) + ".slui"));
			if (text == null || !File.Exists(text))
			{
				return true;
			}
			DateTime lastWriteTimeUtc = File.GetLastWriteTimeUtc(text);
			if (_activeKeys == null || _activePath != text || _activeWritten != lastWriteTimeUtc)
			{
				_activePath = text;
				_activeWritten = lastWriteTimeUtc;
				_activeKeys = new HashSet<string>(from pair in PresetFix.Read(text)
					select pair.Key, StringComparer.Ordinal);
			}
			return _activeKeys.Contains(definition.Section + "/" + definition.Key);
		}

		private static Mirror Bind(ConfigEntryBase entry)
		{
			//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_0047: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004d: Expected O, but got Unknown
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0092: Expected O, but got Unknown
			try
			{
				ConfigDescription description = entry.Description;
				string obj = ((description != null) ? description.Description : null) ?? "";
				ConfigDescription description2 = entry.Description;
				ConfigDescription val = new ConfigDescription(obj, (description2 != null) ? description2.AcceptableValues : null, new object[1] { (object)new ConfigurationManagerAttributes
				{
					Browsable = false
				} });
				ConfigEntryBase val2 = (ConfigEntryBase)BindDefinition.MakeGenericMethod(entry.SettingType).Invoke(Prefs.Cfg, new object[3] { entry.Definition, entry.DefaultValue, val });
				string serializedValue = val2.GetSerializedValue();
				string text = TomlTypeConverter.ConvertToString(entry.DefaultValue, entry.SettingType);
				if (serializedValue != text)
				{
					entry.SetSerializedValue(serializedValue);
				}
				else
				{
					val2.SetSerializedValue(entry.GetSerializedValue());
				}
				return new Mirror
				{
					Entry = val2,
					Last = val2.GetSerializedValue()
				};
			}
			catch (Exception)
			{
				return null;
			}
		}

		private static IEnumerable<ConfigEntryBase> Unkept(Elem e)
		{
			if (Unsaved != null)
			{
				return from entry in Settings.Select(delegate(FieldInfo field)
					{
						object? value = field.GetValue(e);
						return (ConfigEntryBase)((value is ConfigEntryBase) ? value : null);
					})
					where entry != null && entry.ConfigFile == Unsaved
					select entry;
			}
			return Array.Empty<ConfigEntryBase>();
		}

		private Dictionary<string, string> Kept()
		{
			if (_kept != null)
			{
				return _kept;
			}
			_kept = new Dictionary<string, string>(StringComparer.Ordinal);
			string[] array = (ElementLook.Kept?.Value ?? "").Split(new char[1] { ';' });
			foreach (string text in array)
			{
				int num = text.IndexOf('=');
				if (num > 0)
				{
					_kept[Uri.UnescapeDataString(text.Substring(0, num))] = Uri.UnescapeDataString(text.Substring(num + 1));
				}
			}
			return _kept;
		}

		private static IEnumerable<ConfigEntryBase> Saved(Elem e)
		{
			if (Unsaved != null)
			{
				return from entry in Settings.Select(delegate(FieldInfo field)
					{
						object? value = field.GetValue(e);
						return (ConfigEntryBase)((value is ConfigEntryBase) ? value : null);
					})
					where entry != null && entry.ConfigFile != Unsaved
					select entry;
			}
			return Array.Empty<ConfigEntryBase>();
		}

		private void Restore(Elem e)
		{
			Dictionary<string, string> dictionary = Kept();
			bool flag = false;
			foreach (ConfigEntryBase item in Saved(e))
			{
				if (!dictionary.TryGetValue(item.Definition.Key, out var value))
				{
					continue;
				}
				try
				{
					if (item.GetSerializedValue() == Default(item))
					{
						item.SetSerializedValue(value);
					}
				}
				catch (Exception)
				{
				}
				dictionary.Remove(item.Definition.Key);
				flag = true;
			}
			if (flag && ElementLook.Kept != null)
			{
				ElementLook.Kept.Value = string.Join(";", dictionary.Select((KeyValuePair<string, string> pair) => Uri.EscapeDataString(pair.Key) + "=" + Uri.EscapeDataString(pair.Value)));
			}
			foreach (ConfigEntryBase item2 in Unkept(e))
			{
				if (dictionary.TryGetValue(item2.Definition.Key, out var value2))
				{
					try
					{
						item2.SetSerializedValue(value2);
					}
					catch (Exception)
					{
						dictionary.Remove(item2.Definition.Key);
					}
				}
			}
		}

		private void Keep()
		{
			if (ElementLook.Kept == null)
			{
				return;
			}
			Dictionary<string, string> dictionary = Kept();
			bool flag = false;
			foreach (var registration in SeneaLHud.Registrations)
			{
				string item = registration.Item1;
				Elem val = Elem(item);
				if (val == null || !_restored.Contains(item))
				{
					continue;
				}
				foreach (ConfigEntryBase item2 in Unkept(val))
				{
					string serializedValue = item2.GetSerializedValue();
					string key = item2.Definition.Key;
					bool flag2 = serializedValue == TomlTypeConverter.ConvertToString(item2.DefaultValue, item2.SettingType);
					bool num;
					if (!flag2)
					{
						if (!dictionary.TryGetValue(key, out var value))
						{
							goto IL_00c1;
						}
						num = value != serializedValue;
					}
					else
					{
						num = dictionary.Remove(key);
					}
					if (!num)
					{
						continue;
					}
					goto IL_00c1;
					IL_00c1:
					if (!flag2)
					{
						dictionary[key] = serializedValue;
					}
					flag = true;
				}
			}
			if (flag)
			{
				ElementLook.Kept.Value = string.Join(";", dictionary.Select((KeyValuePair<string, string> pair) => Uri.EscapeDataString(pair.Key) + "=" + Uri.EscapeDataString(pair.Value)));
			}
		}

		private static void ScaleText(RectTransform rect, State state, float scale)
		{
			if (scale == state.Scale && Time.unscaledTime < state.NextTextCheck)
			{
				return;
			}
			state.NextTextCheck = Time.unscaledTime + 0.5f;
			List<TMP_Text> list = new List<TMP_Text>();
			foreach (TMP_Text key in state.BaseSizes.Keys)
			{
				if ((Object)(object)key == (Object)null)
				{
					list.Add(key);
				}
			}
			foreach (TMP_Text item in list)
			{
				state.BaseSizes.Remove(item);
			}
			bool flag = scale != state.Scale;
			state.Scale = scale;
			TMP_Text[] componentsInChildren = ((Component)rect).GetComponentsInChildren<TMP_Text>(true);
			foreach (TMP_Text val in componentsInChildren)
			{
				if (!state.BaseSizes.TryGetValue(val, out var value))
				{
					value = (state.BaseSizes[val] = val.fontSize);
					flag = true;
				}
				if (flag && !Mathf.Approximately(val.fontSize, value * scale))
				{
					val.fontSize = value * scale;
				}
			}
		}

		static ElementLooks()
		{
			object? obj = AccessTools.Field(typeof(Prefs), "Quiet")?.GetValue(null);
			Unsaved = (ConfigFile)((obj is ConfigFile) ? obj : null);
			BindDefinition = typeof(ConfigFile).GetMethods().FirstOrDefault((MethodInfo m) => m.Name == "Bind" && m.IsGenericMethodDefinition && m.GetParameters().Length == 3 && m.GetParameters()[0].ParameterType == typeof(ConfigDefinition) && m.GetParameters()[2].ParameterType == typeof(ConfigDescription));
		}
	}
	internal class ElementTarget : EditTarget
	{
		protected readonly ExtRig Rig;

		public readonly string Id;

		public readonly ElementMode Mode;

		private readonly List<Action<List<EditOption>>> _content = new List<Action<List<EditOption>>>();

		public override bool HasPlace => true;

		public override bool HasCaption => true;

		public override bool HasColors => true;

		public override bool HasRotation => true;

		public override bool IsTab => (int)Mode == 1;

		public override string Name => Rig.Name;

		public override bool Present
		{
			get
			{
				if (Rig.Alive)
				{
					return base.E.On.Value;
				}
				return false;
			}
		}

		public override bool Editable
		{
			get
			{
				//IL_001d: 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)
				if (((EditTarget)this).Present && ((EditTarget)this).Shown && Rig.Shown)
				{
					return SeneaLHud.EditorMode == Mode;
				}
				return false;
			}
		}

		public override string IdleLabel => Loc.HudIdleNothing;

		public override bool Shown
		{
			get
			{
				if (base.E.On.Value)
				{
					return !base.E.Hidden;
				}
				return false;
			}
			set
			{
				if (value)
				{
					base.E.On.Value = true;
				}
				base.E.Hide.Value = !value;
			}
		}

		public override int Anim
		{
			get
			{
				//IL_000b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0011: Expected I4, but got Unknown
				return (int)base.E.Anim.Value;
			}
			set
			{
				base.E.Anim.Value = (Fx)value;
			}
		}

		public ElementTarget(ExtRig rig)
			: base(rig.E)
		{
			//IL_0050: 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)
			Rig = rig;
			string text = rig.E.Key ?? "";
			Id = text.Substring(text.LastIndexOf('.') + 1);
			Mode = SeneaLHud.ModeOf(Id);
			if (ElementContent.Options.TryGetValue(Id, out var value))
			{
				_content.Add(value);
			}
		}

		public static bool Ours(EditTarget target)
		{
			if (target is ExtTarget && target.E?.Key != null)
			{
				return target.E.Key.IndexOf("alkeari.valheim.senealuiunlocker", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		public override Rect Frame()
		{
			//IL_0006: Unknown result type (might be due to in