Decompiled source of VikingDex v1.0.0

plugins/VikingDex.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Splatform;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.UI;
using Valheim.SettingsGui;
using Valheim.UI;
using VikingDex.Animals;
using VikingDex.Core;
using VikingDex.Creatures;
using VikingDex.UI;

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

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace VikingDex
{
	[BepInPlugin("ff15vikings.vikingdex", "VikingDex", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "ff15vikings.vikingdex";

		public const string Name = "VikingDex";

		public const string Version = "1.0.0";

		private Harmony _harmony;

		private FileWatcher _configWatcher;

		internal static Plugin Instance { get; private set; }

		internal static bool IsHeadless => (int)SystemInfo.graphicsDeviceType == 4;

		internal static void IgnoreOwnConfigSave()
		{
			Instance?._configWatcher?.IgnoreOwnSave();
		}

		private void Awake()
		{
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0067: Expected O, but got Unknown
			Instance = this;
			Log.Init(((BaseUnityPlugin)this).Logger);
			ModConfig.Init(((BaseUnityPlugin)this).Config);
			DexConfig.Bind();
			ModConfig.FinishBinding();
			_configWatcher = new FileWatcher(((BaseUnityPlugin)this).Config.ConfigFilePath, delegate
			{
				((BaseUnityPlugin)this).Config.Reload();
				Log.Info("Config file reloaded.");
				ConfigSync.Broadcast();
			});
			CreatureFile.Init();
			AnimalExtras.Init();
			Carrying.Init();
			_harmony = new Harmony("ff15vikings.vikingdex");
			Patch(typeof(VersionCheck), "Core.VersionCheck", required: true);
			Patch(typeof(ConsoleCommands), "Core.ConsoleCommands", required: false);
			if (!IsHeadless)
			{
				Patch(typeof(VersionCheck.ConnectErrorPatch), "Core.ConnectErrorMessage", required: false);
			}
			Patch(typeof(CreatureRegistry), "Creatures.Registry", required: true);
			Patch(typeof(CreatureFile), "Creatures.File", required: false);
			Patch(typeof(AnimalIndex), "Animals.Index", required: true);
			Patch(typeof(DexEvents), "Animals.Events", required: false);
			Patch(typeof(TamingHooks), "Animals.TamingHooks", required: false);
			Patch(typeof(AnimalOrders), "Animals.Orders", required: false);
			Patch(typeof(AnimalBehavior), "Animals.Behavior", required: false);
			Patch(typeof(AnimalExtras), "Animals.Extras", required: false);
			Carrying.HidingWorks = Patch(typeof(Carrying.Hiding), "Animals.Carrying.Hiding", required: false) && Patch(typeof(Carrying), "Animals.Carrying", required: false);
			if (!IsHeadless)
			{
				Patch(typeof(CommandWheel), "UI.CommandWheel", required: false);
				DexWindow.Init();
				Notifications.Init();
				Patch(typeof(MenuHooks), "UI.MenuHooks", required: false);
			}
			Log.Info("VikingDex 1.0.0 loaded (" + (IsHeadless ? "dedicated server" : "client") + ").");
		}

		private void Start()
		{
			ConflictCheck.Run();
		}

		private void Update()
		{
			_configWatcher?.Tick();
			CreatureFile.Tick();
			AnimalIndex.ServerTick();
			if (!IsHeadless)
			{
				AnimalClient.Tick();
				AnimalExtras.TickCatchUp();
				Carrying.ClientTick();
				CarryHud.Tick();
				CommandWheel.Tick();
				DexWindow.Tick();
				MapMarkers.Tick();
			}
		}

		private void OnDestroy()
		{
			_configWatcher?.Stop();
			CreatureFile.Stop();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private bool Patch(Type patchClass, string feature, bool required)
		{
			try
			{
				_harmony.CreateClassProcessor(patchClass).Patch();
				Log.Debug("Patched " + feature);
				return true;
			}
			catch (Exception arg)
			{
				Log.Error(string.Format("Failed to patch {0}{1}: {2}", feature, required ? " (required!)" : ", feature disabled", arg));
				return false;
			}
		}
	}
	public enum AnimalMode
	{
		Roam,
		Follow,
		Stay
	}
	public enum FightStyle
	{
		Normal,
		Aggressive,
		Protective,
		Calm
	}
	public sealed class CreatureOptions
	{
		public bool? Show;

		public string Species;

		public string DisplayName;

		public string IconItem;

		public Sprite Icon;

		public bool? Alerts;

		public bool? CanFollow;

		public bool? CanStay;

		public bool? CanRoam;

		public bool? CanFight;

		public float? MaxStayRadius;

		public int? BreedingLimit;

		public float? BreedingCheckRange;

		public Func<Character, Player, bool> OnFollow;

		public Func<Character, Vector3, float, bool> OnStay;

		public Func<Character, bool> OnRoam;

		public Func<Character, FightStyle, bool> OnFightStyle;

		public bool? CanCarry;

		public float? Weight;

		public bool? CanUsePortals;

		public Func<Character, Player, bool> AllowCarry;

		public Func<Character, Player, bool> AllowPortal;
	}
	public static class VikingDexApi
	{
		public const int Version = 3;

		internal static readonly Dictionary<string, CreatureOptions> Registered = new Dictionary<string, CreatureOptions>();

		internal static readonly Dictionary<string, List<Func<ZDO, string>>> StatusLines = new Dictionary<string, List<Func<ZDO, string>>>();

		public static event Action<Character> Tamed;

		public static event Action<Character> Died;

		public static event Action<Character> ModeChanged;

		public static event Action<ZDO> PickedUp;

		public static event Action<ZDO> PutDown;

		public static event Action<ZDO> WentThroughPortal;

		public static void Register(string prefabName, CreatureOptions options)
		{
			if (!string.IsNullOrEmpty(prefabName) && options != null)
			{
				Registered[prefabName] = options;
				CreatureRegistry.OnApiChanged();
			}
		}

		public static void AddStatusLine(string prefabName, Func<ZDO, string> line)
		{
			if (!string.IsNullOrEmpty(prefabName) && line != null)
			{
				if (!StatusLines.TryGetValue(prefabName, out var value))
				{
					value = (StatusLines[prefabName] = new List<Func<ZDO, string>>());
				}
				value.Add(line);
			}
		}

		public static bool IsCarried(ZDO zdo)
		{
			if (zdo != null)
			{
				return zdo.GetLong(DexKeys.Carrier, 0L) != 0;
			}
			return false;
		}

		public static long GetCarrierId(ZDO zdo)
		{
			if (zdo == null)
			{
				return 0L;
			}
			return zdo.GetLong(DexKeys.Carrier, 0L);
		}

		public static string GetCarrierName(ZDO zdo)
		{
			if (!IsCarried(zdo))
			{
				return "";
			}
			return zdo.GetString(DexKeys.CarrierName, "");
		}

		public static AnimalMode GetMode(ZDO zdo)
		{
			return AnimalOrders.ModeOf(zdo);
		}

		public static FightStyle GetFightStyle(ZDO zdo)
		{
			return AnimalOrders.FightOf(zdo);
		}

		public static float GetStayRadius(ZDO zdo)
		{
			return AnimalOrders.RadiusOf(zdo);
		}

		public static string GetTamer(ZDO zdo)
		{
			return ((zdo != null) ? zdo.GetString(DexKeys.Tamer, "") : null) ?? "";
		}

		public static long GetTamerId(ZDO zdo)
		{
			if (zdo == null)
			{
				return 0L;
			}
			return zdo.GetLong(DexKeys.TamerId, 0L);
		}

		public static bool IsKnownCreature(string prefabName)
		{
			if (CreatureRegistry.TryGet(prefabName, out var info))
			{
				return info.Show;
			}
			return false;
		}

		internal static void RaiseTamed(Character character)
		{
			Raise(VikingDexApi.Tamed, character, "Tamed");
		}

		internal static void RaiseDied(Character character)
		{
			Raise(VikingDexApi.Died, character, "Died");
		}

		internal static void RaiseModeChanged(Character character)
		{
			Raise(VikingDexApi.ModeChanged, character, "ModeChanged");
		}

		internal static void RaisePickedUp(ZDO zdo)
		{
			Raise(VikingDexApi.PickedUp, zdo, "PickedUp");
		}

		internal static void RaisePutDown(ZDO zdo)
		{
			Raise(VikingDexApi.PutDown, zdo, "PutDown");
		}

		internal static void RaiseWentThroughPortal(ZDO zdo)
		{
			Raise(VikingDexApi.WentThroughPortal, zdo, "WentThroughPortal");
		}

		internal static bool Allows(string prefab, Func<CreatureOptions, Func<Character, Player, bool>> pick, Character animal, Player player)
		{
			if (!Registered.TryGetValue(prefab, out var value))
			{
				return true;
			}
			Func<Character, Player, bool> func = pick(value);
			if (func == null)
			{
				return true;
			}
			try
			{
				return func(animal, player);
			}
			catch (Exception ex)
			{
				Log.Warn("A mod's rule for " + prefab + " failed: " + ex.Message);
				return true;
			}
		}

		internal static bool TryCallback(string prefab, Func<CreatureOptions, bool> call)
		{
			if (!Registered.TryGetValue(prefab, out var value))
			{
				return false;
			}
			try
			{
				return call(value);
			}
			catch (Exception ex)
			{
				Log.Warn("A mod's command handler for " + prefab + " failed: " + ex.Message);
				return false;
			}
		}

		private static void Raise<T>(Action<T> handlers, T arg, string name)
		{
			if (handlers == null)
			{
				return;
			}
			Delegate[] invocationList = handlers.GetInvocationList();
			foreach (Delegate obj in invocationList)
			{
				try
				{
					((Action<T>)obj)(arg);
				}
				catch (Exception ex)
				{
					Log.Warn("A mod's " + name + " handler failed (" + obj.Method.DeclaringType?.FullName + "): " + ex.Message);
				}
			}
		}
	}
}
namespace VikingDex.UI
{
	internal sealed class AnimalCard
	{
		internal const float Height = 150f;

		private const float Left = 106f;

		private const float RightText = 240f;

		internal GameObject Root;

		internal ZDOID Id;

		internal Vector3 Pos;

		internal string Label = "";

		internal bool Editing;

		internal AnimalEntry Entry;

		private readonly Image _icon;

		private readonly TextMeshProUGUI _letter;

		private readonly TextMeshProUGUI _title;

		private readonly TextMeshProUGUI _status;

		private readonly TextMeshProUGUI _details;

		private readonly TextMeshProUGUI _where;

		private readonly GameObject _healthBar;

		private readonly RectTransform _healthFill;

		private readonly TextMeshProUGUI _healthText;

		private readonly Button _rename;

		private readonly TMP_InputField _nameInput;

		private readonly GameObject _modeBox;

		private readonly GameObject _fightBox;

		private readonly GameObject _radiusBox;

		private readonly TextMeshProUGUI _mode;

		private readonly TextMeshProUGUI _fight;

		private readonly TextMeshProUGUI _radius;

		private readonly GameObject _putDown;

		private string _currentName = "";

		internal AnimalCard(RectTransform list, Action<AnimalCard> where, Action<AnimalCard, string> rename, Action<AnimalCard, int> stepMode, Action<AnimalCard, int> stepFight, Action<AnimalCard, int> stepRadius, Action<AnimalCard> putDown)
		{
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: 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_00fa: 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_01ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0220: Unknown result type (might be due to invalid IL or missing references)
			//IL_025a: 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_0315: Unknown result type (might be due to invalid IL or missing references)
			//IL_0324: 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_0342: Unknown result type (might be due to invalid IL or missing references)
			//IL_037b: Unknown result type (might be due to invalid IL or missing references)
			//IL_039d: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0405: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Unknown result type (might be due to invalid IL or missing references)
			//IL_0434: Unknown result type (might be due to invalid IL or missing references)
			//IL_0443: Unknown result type (might be due to invalid IL or missing references)
			//IL_0452: Unknown result type (might be due to invalid IL or missing references)
			//IL_0467: Unknown result type (might be due to invalid IL or missing references)
			//IL_0490: Unknown result type (might be due to invalid IL or missing references)
			//IL_049f: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_04bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0508: Unknown result type (might be due to invalid IL or missing references)
			//IL_0517: Unknown result type (might be due to invalid IL or missing references)
			//IL_0526: Unknown result type (might be due to invalid IL or missing references)
			//IL_05de: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_05fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_060b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0650: Unknown result type (might be due to invalid IL or missing references)
			//IL_065f: Unknown result type (might be due to invalid IL or missing references)
			//IL_066e: Unknown result type (might be due to invalid IL or missing references)
			//IL_067d: Unknown result type (might be due to invalid IL or missing references)
			AnimalCard animalCard = this;
			RectTransform val = UiKit.Child((Transform)(object)list, "Card");
			Root = ((Component)val).gameObject;
			LayoutElement obj = Root.AddComponent<LayoutElement>();
			obj.minHeight = (obj.preferredHeight = 150f);
			((Graphic)Root.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.28f);
			RectTransform val2 = UiKit.Child((Transform)(object)val, "IconFrame").Place(new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(12f, -12f), new Vector2(80f, 80f));
			((Graphic)((Component)val2).gameObject.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.45f);
			RectTransform val3 = UiKit.Child((Transform)(object)val2, "Icon").Stretch(6f, 6f, 6f, 6f);
			_icon = ((Component)val3).gameObject.AddComponent<Image>();
			_icon.preserveAspect = true;
			((Graphic)_icon).raycastTarget = false;
			_letter = UiKit.Text(UiKit.Child((Transform)(object)val2, "Letter").Stretch(), "", UiKit.Font.Title, 40f, UiKit.Orange, (TextAlignmentOptions)514);
			_title = UiKit.Text(Row(val, 8f, 30f, 106f, 200f), "", UiKit.Font.Label, 21f, UiKit.Orange, (TextAlignmentOptions)4097);
			_status = UiKit.Text(Row(val, 40f, 22f, 106f, 240f), "", UiKit.Font.Label, 16f, UiKit.DescriptionText, (TextAlignmentOptions)4097);
			_details = UiKit.Text(Row(val, 63f, 20f, 106f, 240f), "", UiKit.Font.Label, 15f, UiKit.DimText, (TextAlignmentOptions)4097);
			_where = UiKit.Text(Row(val, 85f, 20f, 106f, 240f), "", UiKit.Font.Label, 14f, UiKit.DimText, (TextAlignmentOptions)4097);
			TextMeshProUGUI[] array = (TextMeshProUGUI[])(object)new TextMeshProUGUI[3] { _status, _details, _where };
			foreach (TextMeshProUGUI obj2 in array)
			{
				((TMP_Text)obj2).enableAutoSizing = true;
				((TMP_Text)obj2).fontSizeMin = 11f;
				((TMP_Text)obj2).fontSizeMax = ((TMP_Text)obj2).fontSize;
			}
			RectTransform val4 = UiKit.Child((Transform)(object)val, "Health").Place(new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-14f, -14f), new Vector2(170f, 12f));
			_healthBar = ((Component)val4).gameObject;
			((Graphic)((Component)val4).gameObject.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.6f);
			_healthFill = UiKit.Child((Transform)(object)val4, "Fill");
			_healthFill.anchorMin = Vector2.zero;
			_healthFill.anchorMax = Vector2.one;
			_healthFill.offsetMin = new Vector2(2f, 2f);
			_healthFill.offsetMax = new Vector2(-2f, -2f);
			((Graphic)((Component)_healthFill).gameObject.AddComponent<Image>()).color = UiKit.Hex(12597547u);
			_healthText = UiKit.Text(UiKit.Child((Transform)(object)val, "HealthText").Place(new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-14f, -28f), new Vector2(170f, 18f)), "", UiKit.Font.Value, 13f, UiKit.DescriptionText, (TextAlignmentOptions)4100);
			UiKit.Button(UiKit.Child((Transform)(object)val, "Where").Place(new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-14f, -52f), new Vector2(104f, 32f)), "Where?", 15f, delegate
			{
				where(animalCard);
			});
			_rename = UiKit.Button(UiKit.Child((Transform)(object)val, "Rename").Place(new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-124f, -52f), new Vector2(104f, 32f)), "Rename", 15f, StartRename);
			_modeBox = Stepper(val, 0f, 180f, delegate(int step)
			{
				stepMode(animalCard, step);
			}, out _mode);
			_fightBox = Stepper(val, 188f, 200f, delegate(int step)
			{
				stepFight(animalCard, step);
			}, out _fight);
			_radiusBox = Stepper(val, 396f, 150f, delegate(int step)
			{
				stepRadius(animalCard, step);
			}, out _radius);
			_putDown = ((Component)UiKit.Button(UiKit.Child((Transform)(object)val, "PutDown").Place(new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(106f, 10f), new Vector2(160f, 32f)), "Put down", 15f, delegate
			{
				putDown(animalCard);
			})).gameObject;
			_nameInput = UiKit.InputField(UiKit.Child((Transform)(object)val, "NameInput").Place(new Vector2(0f, 1f), new Vector2(0f, 1f), new Vector2(106f, -8f), new Vector2(240f, 30f)), "Name", 10, delegate
			{
				animalCard.StopRename();
			});
			((UnityEvent<string>)(object)_nameInput.onSubmit).AddListener((UnityAction<string>)delegate(string value)
			{
				rename(animalCard, value);
			});
			((Component)_nameInput).gameObject.SetActive(false);
		}

		private static GameObject Stepper(RectTransform root, float x, float width, Action<int> onStep, out TextMeshProUGUI value)
		{
			//IL_0015: 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_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_0040: Unknown result type (might be due to invalid IL or missing references)
			RectTransform val = UiKit.Child((Transform)(object)root, "Stepper").Place(new Vector2(0f, 0f), new Vector2(0f, 0f), new Vector2(106f + x, 10f), new Vector2(width, 30f));
			value = UiKit.Stepper(val, onStep);
			((TMP_Text)value).fontSize = 14f;
			return ((Component)val).gameObject;
		}

		private static RectTransform Row(RectTransform parent, float top, float height, float left, float right)
		{
			//IL_0016: 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_0040: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: 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)
			RectTransform obj = UiKit.Child((Transform)(object)parent, "Row");
			obj.anchorMin = new Vector2(0f, 1f);
			obj.anchorMax = new Vector2(1f, 1f);
			obj.pivot = new Vector2(0f, 1f);
			obj.anchoredPosition = new Vector2(left, 0f - top);
			obj.sizeDelta = new Vector2(0f - left - right, height);
			return obj;
		}

		internal void Fill(ZDOID id, Vector3 pos, CardText text, Sprite icon, string letter, string currentName, AnimalEntry entry)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_0016: 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_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Unknown result type (might be due to invalid IL or missing references)
			if (Id != id)
			{
				StopRename();
			}
			Id = id;
			Pos = pos;
			Entry = entry;
			Label = text.Title;
			_icon.sprite = icon;
			((Behaviour)_icon).enabled = (Object)(object)icon != (Object)null;
			((TMP_Text)_letter).text = (((Object)(object)icon == (Object)null && !string.IsNullOrEmpty(letter)) ? letter.Substring(0, 1).ToUpperInvariant() : "");
			((TMP_Text)_title).text = text.Title;
			((TMP_Text)_status).text = text.Status;
			((TMP_Text)_details).text = text.Details;
			((TMP_Text)_where).text = text.Where;
			_healthBar.SetActive(text.HealthFraction >= 0f);
			((TMP_Text)_healthText).text = ((text.HealthFraction >= 0f) ? text.HealthText : "");
			if (text.HealthFraction >= 0f)
			{
				_healthFill.anchorMax = new Vector2(Mathf.Max(0.01f, text.HealthFraction), 1f);
			}
			((Component)_rename).gameObject.SetActive(text.CanRename);
			_currentName = currentName ?? "";
			if (!Editing)
			{
				((Component)_title).gameObject.SetActive(true);
			}
			_modeBox.SetActive(text.ModeText != null);
			_fightBox.SetActive(text.FightText != null);
			_radiusBox.SetActive(text.RadiusText != null);
			((TMP_Text)_mode).text = text.ModeText ?? "";
			((TMP_Text)_fight).text = text.FightText ?? "";
			((TMP_Text)_radius).text = text.RadiusText ?? "";
			_putDown.SetActive(text.CanPutDown);
		}

		private void StartRename()
		{
			Editing = true;
			((Component)_title).gameObject.SetActive(false);
			((Component)_nameInput).gameObject.SetActive(true);
			_nameInput.text = _currentName;
			_nameInput.ActivateInputField();
			((Selectable)_nameInput).Select();
		}

		internal void StopRename()
		{
			if (Editing)
			{
				Editing = false;
				if ((Object)(object)_nameInput != (Object)null)
				{
					((Component)_nameInput).gameObject.SetActive(false);
				}
				if ((Object)(object)_title != (Object)null)
				{
					((Component)_title).gameObject.SetActive(true);
				}
			}
		}
	}
	internal sealed class CardText
	{
		public string Title = "";

		public string Status = "";

		public string Details = "";

		public string Where = "";

		public float HealthFraction = -1f;

		public string HealthText = "";

		public bool CanRename;

		public string ModeText;

		public string FightText;

		public string RadiusText;

		public bool CanPutDown;

		private const string Sep = " · ";

		internal static CardText ForAnimal(AnimalEntry e, CreatureInfo info, Vector3 me, bool canRename)
		{
			//IL_04a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a3: Unknown result type (might be due to invalid IL or missing references)
			CardText cardText = new CardText
			{
				HealthFraction = ((e.MaxHealth > 0f) ? Mathf.Clamp01(e.Health / e.MaxHealth) : (-1f)),
				HealthText = $"{Mathf.CeilToInt(Mathf.Max(0f, e.Health))} / {Mathf.CeilToInt(e.MaxHealth)}"
			};
			DateTime time = ZNet.instance.GetTime();
			double num = ((info != null && e.LastFed != 0L) ? ((double)info.FedDuration - (time - new DateTime(e.LastFed)).TotalSeconds) : (-1.0));
			bool flag = num < 0.0;
			if (e.Tamed)
			{
				cardText.Title = AnimalText.Title(e.Name, e.NameAuthor, info, e.Level);
				cardText.CanRename = canRename;
				List<string> list = new List<string>(4);
				bool flag2 = e.CarrierId != 0;
				if (flag2)
				{
					bool flag3 = (Object)(object)Player.m_localPlayer != (Object)null && e.CarrierId == Player.m_localPlayer.GetPlayerID();
					list.Add((e.CarryReason == 2) ? ("Going through a portal with " + e.CarrierName) : (flag3 ? "Carried by you" : ("Carried by " + e.CarrierName)));
				}
				else if (!string.IsNullOrEmpty(e.Follow))
				{
					list.Add("Following " + e.Follow);
				}
				else
				{
					list.Add(e.Patrol ? $"Staying ({Mathf.RoundToInt(StayRadius(e, info))} m)" : "Roaming");
				}
				if (info != null && info.CanFight && e.Fight > 0 && e.Fight <= 3)
				{
					FightStyle fight = (FightStyle)e.Fight;
					list.Add(fight.ToString());
				}
				list.Add((e.Alert && e.Active) ? "Frightened" : (flag ? "Hungry" : "Happy"));
				if (e.Ridden)
				{
					list.Add("Being ridden");
				}
				if (!e.Active && !flag2)
				{
					list.Add("Paused: nobody nearby");
				}
				cardText.Status = string.Join(" · ", list);
				List<string> list2 = new List<string>(4);
				if (info != null && info.FedDuration > 0f)
				{
					list2.Add(flag ? "Hungry: feed it" : ("Fed for " + AnimalText.Time(num) + " more"));
				}
				string text = Breeding(e, info, time, flag);
				if (text != null)
				{
					list2.Add(text);
				}
				string text2 = GrowsUp(e, info, time);
				if (text2 != null)
				{
					list2.Add(text2);
				}
				list2.AddRange(e.Extra);
				cardText.Details = string.Join(" · ", list2);
			}
			else
			{
				float num2 = ((info != null) ? Mathf.Max(1f, info.TamingTime) : 1f);
				int num3 = Mathf.FloorToInt((1f - Mathf.Clamp01(e.TameTimeLeft / num2)) * 100f);
				string arg = AnimalText.Title("", "", info, e.Level);
				cardText.Title = $"{arg}: taming {num3}%";
				if (!e.Active && !e.RemoteTaming)
				{
					cardText.Status = "Paused: nobody nearby";
				}
				else if (e.Alert)
				{
					cardText.Status = "Paused: frightened";
				}
				else if (flag)
				{
					cardText.Status = "Paused: hungry, put food near it";
				}
				else
				{
					cardText.Status = "Tamed in ~" + AnimalText.Time(e.TameTimeLeft) + " if it stays fed and calm" + (e.RemoteTaming ? " (a player is within taming range)" : "");
				}
				List<string> list3 = new List<string>(3);
				if (info != null && info.FedDuration > 0f)
				{
					if (!flag)
					{
						list3.Add("Fed for " + AnimalText.Time(num) + " more");
					}
					double num4 = (double)e.TameTimeLeft - Math.Max(0.0, num);
					int num5 = ((num4 > 0.0) ? ((int)Math.Ceiling(num4 / (double)info.FedDuration)) : 0);
					list3.Add((num5 <= 0) ? "Has eaten enough to finish" : ((num5 == 1) ? "Needs about 1 more feeding" : $"Needs about {num5} more feedings"));
				}
				list3.AddRange(e.Extra);
				cardText.Details = string.Join(" · ", list3);
			}
			cardText.Where = AnimalText.Distance(me, e.Pos);
			if (!string.IsNullOrEmpty(e.Tamer))
			{
				cardText.Where = cardText.Where + " · tamed by " + e.Tamer;
			}
			if (e.Saddle)
			{
				cardText.Where += " · saddled";
			}
			return cardText;
		}

		internal static float StayRadius(AnimalEntry e, CreatureInfo info)
		{
			return Mathf.Clamp((e.Radius > 0f) ? e.Radius : DexConfig.StayRadius.Value, 2f, Mathf.Max(2f, AnimalOrders.MaxRadius(info)));
		}

		private static string Breeding(AnimalEntry e, CreatureInfo info, DateTime now, bool hungry)
		{
			if (info == null || !info.CanBreed || info.IsBaby)
			{
				return null;
			}
			string text = (info.OffspringIsEgg ? "Egg" : "Baby");
			if (e.Pregnant != 0L)
			{
				double num = (double)info.PregnancyDuration - (now - new DateTime(e.Pregnant)).TotalSeconds;
				if (!(num > 0.0))
				{
					return text + " any moment";
				}
				return text + " in " + AnimalText.Time(num);
			}
			if (hungry)
			{
				return "No breeding while hungry";
			}
			if (e.Nearby >= 0 && e.Nearby >= info.EffectiveMaxCreatures)
			{
				return $"Too many animals nearby ({e.Nearby}/{info.EffectiveMaxCreatures}): no breeding";
			}
			if (!info.OffspringIsEgg)
			{
				return $"Ready to breed (love {e.LovePoints}/{info.LovePointsNeeded})";
			}
			return $"Ready to lay (love {e.LovePoints}/{info.LovePointsNeeded})";
		}

		private static string GrowsUp(AnimalEntry e, CreatureInfo info, DateTime now)
		{
			if (info == null || info.GrowTime <= 0f || e.SpawnTime == 0L)
			{
				return null;
			}
			double num = (double)info.GrowTime - (now - new DateTime(e.SpawnTime)).TotalSeconds;
			if (!(num > 0.0))
			{
				return "Grows up any moment";
			}
			return "Grows up in " + AnimalText.Time(num);
		}

		internal static CardText ForLost(LostEntry lost, CreatureInfo info, Vector3 me)
		{
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			return new CardText
			{
				Title = AnimalText.Title(lost.Name, lost.NameAuthor, info, lost.Level),
				Status = (lost.Vanished ? "Vanished " : "Died ") + AnimalText.Ago((ZNet.instance.GetTime() - new DateTime(lost.Time)).TotalSeconds),
				Details = (lost.Vanished ? "Gone from the world without dying. Last seen here" : "") + (string.IsNullOrEmpty(lost.Tamer) ? "" : ((lost.Vanished ? " · " : "") + "Tamed by " + lost.Tamer)),
				Where = AnimalText.Distance(me, lost.Pos)
			};
		}
	}
	internal static class CarryHud
	{
		private static readonly Color TextColor = new Color(1f, 0.86f, 0.5f);

		private static readonly Vector3[] Corners = (Vector3[])(object)new Vector3[4];

		private static TextMeshProUGUI _text;

		private static Minimap _map;

		private static bool _failed;

		internal static void Tick()
		{
			if (_failed)
			{
				return;
			}
			try
			{
				Minimap instance = Minimap.instance;
				List<CarriedAnimal> myCarried = Carrying.MyCarried;
				if ((Object)(object)instance == (Object)null || (Object)(object)Player.m_localPlayer == (Object)null || myCarried.Count == 0 || !instance.m_smallRoot.activeInHierarchy)
				{
					Hide();
					return;
				}
				if ((Object)(object)_text == (Object)null || (Object)(object)_map != (Object)(object)instance)
				{
					Create(instance);
				}
				string text = ((myCarried.Count == 1) ? Carrying.Title(myCarried[0]) : $"{myCarried.Count} animals");
				string text2 = (DexConfig.CarryWeight.Value ? $"Carrying {text} · {Carrying.CarriedWeight:0.#} kg" : ("Carrying " + text));
				if (((TMP_Text)_text).text != text2)
				{
					((TMP_Text)_text).text = text2;
				}
				Place(instance);
				if (!((Component)_text).gameObject.activeSelf)
				{
					((Component)_text).gameObject.SetActive(true);
				}
			}
			catch (Exception ex)
			{
				_failed = true;
				Hide();
				Log.Warn("The 'Carrying' line is unavailable: " + ex.Message);
			}
		}

		private static void Hide()
		{
			if ((Object)(object)_text != (Object)null && ((Component)_text).gameObject.activeSelf)
			{
				((Component)_text).gameObject.SetActive(false);
			}
		}

		private static void Create(Minimap map)
		{
			//IL_005c: 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_0073: 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_00e6: Unknown result type (might be due to invalid IL or missing references)
			_map = map;
			TMP_Text biomeNameSmall = map.m_biomeNameSmall;
			GameObject obj = Object.Instantiate<GameObject>(((Component)biomeNameSmall).gameObject, map.m_smallRoot.transform.parent, false);
			((Object)obj).name = "VikingDex_Carrying";
			_text = obj.GetComponent<TextMeshProUGUI>();
			RectTransform rectTransform = ((TMP_Text)_text).rectTransform;
			Vector2 val = default(Vector2);
			((Vector2)(ref val))..ctor(0.5f, 0.5f);
			rectTransform.anchorMax = val;
			rectTransform.anchorMin = val;
			rectTransform.pivot = new Vector2(0.5f, 1f);
			rectTransform.sizeDelta = new Vector2(360f, 30f);
			((TMP_Text)_text).alignment = (TextAlignmentOptions)258;
			((TMP_Text)_text).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)_text).overflowMode = (TextOverflowModes)0;
			((TMP_Text)_text).enableAutoSizing = false;
			((TMP_Text)_text).fontSize = Mathf.Max(14f, biomeNameSmall.fontSize * 0.85f);
			((Graphic)_text).color = TextColor;
			((Graphic)_text).raycastTarget = false;
			((TMP_Text)_text).text = "";
			obj.SetActive(false);
		}

		private static void Place(Minimap map)
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_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)
			((Graphic)map.m_mapImageSmall).rectTransform.GetWorldCorners(Corners);
			Vector3 val = (Corners[0] + Corners[3]) * 0.5f;
			float y = ((Transform)((TMP_Text)_text).rectTransform).lossyScale.y;
			((Transform)((TMP_Text)_text).rectTransform).position = val + new Vector3(0f, -34f * y, 0f);
		}
	}
	[HarmonyPatch]
	internal static class CommandWheel
	{
		private sealed class WheelConfig : IRadialConfig
		{
			private readonly Character _animal;

			private readonly string _title;

			private readonly Sprite _icon;

			public string LocalizedName => _title;

			public Sprite Sprite => _icon;

			public WheelConfig(Character animal)
			{
				_animal = animal;
				ZDO zDO = animal.m_nview.GetZDO();
				CreatureInfo creatureInfo = CreatureRegistry.Shown(zDO.GetPrefab());
				_title = AnimalText.Title(zDO.GetString(ZDOVars.s_tamedName, ""), zDO.GetString(ZDOVars.s_tamedNameAuthor, ""), creatureInfo, Mathf.Max(1, zDO.GetInt(ZDOVars.s_level, 1)));
				_icon = creatureInfo?.Icon;
			}

			public void InitRadialConfig(RadialBase radial)
			{
				//IL_0099: 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_02e0: Unknown result type (might be due to invalid IL or missing references)
				//IL_02e5: Unknown result type (might be due to invalid IL or missing references)
				//IL_0297: Unknown result type (might be due to invalid IL or missing references)
				List<RadialMenuElement> list = new List<RadialMenuElement>();
				if ((Object)(object)_animal == (Object)null || (Object)(object)_animal.m_nview == (Object)null || !_animal.m_nview.IsValid())
				{
					radial.ConstructRadial(list);
					return;
				}
				ZDO zDO = _animal.m_nview.GetZDO();
				CreatureInfo creatureInfo = CreatureRegistry.Shown(zDO.GetPrefab());
				if (creatureInfo == null)
				{
					radial.ConstructRadial(list);
					return;
				}
				AnimalMode animalMode = AnimalOrders.ModeOf(zDO);
				FightStyle fightStyle = AnimalOrders.FightOf(zDO);
				int radius = Mathf.RoundToInt(AnimalOrders.RadiusOf(zDO));
				ZDOID id = zDO.m_uid;
				if (creatureInfo.CanFollow)
				{
					list.Add(Element("Follow", "Follow me", "Comes with you.", animalMode == AnimalMode.Follow, () => Order(id, 1, -1, "following you")));
				}
				if (creatureInfo.CanStay)
				{
					list.Add(Element("Stay", "Stay here", $"Stays within {radius} m of this spot (change it in the panel).", animalMode == AnimalMode.Stay, () => Order(id, 2, -1, $"staying here ({radius} m)")));
				}
				if (creatureInfo.CanRoam)
				{
					list.Add(Element("Roam", "Roam free", "Wanders freely, like vanilla.", animalMode == AnimalMode.Roam, () => Order(id, 0, -1, "roaming free")));
				}
				if (creatureInfo.CanFight)
				{
					list.Add(Element("Normal", "Fight: normal", "Fights what it notices or what attacks it, like vanilla.", fightStyle == FightStyle.Normal, () => Order(id, -1, 0, "fighting normally")));
					list.Add(Element("Aggressive", "Fight: aggressive", $"Hunts enemies up to {DexConfig.AggressiveRange.Value:0} m away.", fightStyle == FightStyle.Aggressive, () => Order(id, -1, 1, "aggressive")));
					list.Add(Element("Protective", "Fight: protective", $"Attacks enemies that come within {DexConfig.ProtectiveRange.Value:0} m of you or its spot.", fightStyle == FightStyle.Protective, () => Order(id, -1, 2, "protective")));
					list.Add(Element("Calm", "Fight: calm", "Never fights; runs when hurt.", fightStyle == FightStyle.Calm, () => Order(id, -1, 3, "calm")));
				}
				if (creatureInfo.CanCarry && DexConfig.CarryEnabled.Value)
				{
					string arg = (DexConfig.CarryWeight.Value ? $" It weighs {creatureInfo.Weight:0.#} kg." : "");
					Character animal = _animal;
					list.Add(Element("Carry", "Carry", $"Pick it up and take it with you.{arg} Put it down with {DexConfig.CommandKey.Value} when you're not looking at an animal.", current: false, delegate
					{
						Carrying.RequestCarry(animal);
						return true;
					}));
				}
				foreach (CarriedAnimal item in Carrying.MyCarried)
				{
					ZDOID carriedId = item.Id;
					list.Add(Element("Put down", "Put down " + Carrying.Title(item), "Puts the animal you carry down in front of you.", current: false, delegate
					{
						//IL_0001: Unknown result type (might be due to invalid IL or missing references)
						Carrying.PutDown(carriedId);
						return true;
					}));
				}
				radial.ConstructRadial(list);
			}

			private bool Order(ZDOID id, int mode, int fight, string what)
			{
				//IL_0006: 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)
				AnimalOrders.Send(new OrderRequest
				{
					Id = id,
					Mode = mode,
					Fight = fight
				});
				Player localPlayer = Player.m_localPlayer;
				if (localPlayer != null)
				{
					((Character)localPlayer).Message((MessageType)2, _title + ": " + what, 0, (Sprite)null, false);
				}
				return true;
			}
		}

		private sealed class PutDownConfig : IRadialConfig
		{
			public string LocalizedName => "Put down";

			public Sprite Sprite
			{
				get
				{
					List<CarriedAnimal> myCarried = Carrying.MyCarried;
					if (myCarried.Count <= 0 || !CreatureRegistry.TryGet(myCarried[0].Prefab, out var info))
					{
						return null;
					}
					return info.Icon;
				}
			}

			public void InitRadialConfig(RadialBase radial)
			{
				//IL_0023: Unknown result type (might be due to invalid IL or missing references)
				//IL_0028: Unknown result type (might be due to invalid IL or missing references)
				List<RadialMenuElement> list = new List<RadialMenuElement>();
				foreach (CarriedAnimal item in Carrying.MyCarried)
				{
					ZDOID id = item.Id;
					list.Add(Element("Put down", "Put down " + Carrying.Title(item), "Puts it down in front of you.", current: false, delegate
					{
						//IL_0001: Unknown result type (might be due to invalid IL or missing references)
						Carrying.PutDown(id);
						return true;
					}));
				}
				radial.ConstructRadial(list);
			}
		}

		private static IRadialConfig _opening;

		internal static void Tick()
		{
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			Player localPlayer = Player.m_localPlayer;
			Hud instance = Hud.instance;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)instance == (Object)null || (Object)(object)instance.m_radialMenu == (Object)null)
			{
				return;
			}
			RadialBase radialMenu = instance.m_radialMenu;
			bool flag = IsDown(DexConfig.CommandKey.Value);
			bool flag2 = IsDown(DexConfig.CarryKey.Value);
			if (Hud.InRadial())
			{
				if ((radialMenu.CurrentConfig is WheelConfig || radialMenu.CurrentConfig is PutDownConfig) && flag)
				{
					radialMenu.QueuedClose();
				}
			}
			else
			{
				if ((!flag && !flag2) || !((Character)localPlayer).TakeInput() || Hud.IsPieceSelectionVisible() || ((Character)localPlayer).InPlaceMode())
				{
					return;
				}
				ZDO zdo;
				CreatureInfo info;
				Character val = Hovered(localPlayer, out zdo, out info);
				if (flag2)
				{
					if ((Object)(object)val != (Object)null && info.CanCarry)
					{
						Carrying.RequestCarry(val);
					}
					else if (Carrying.MyCarried.Count > 0)
					{
						Carrying.PutDownFirst();
					}
				}
				else if ((Object)(object)val == (Object)null)
				{
					if (Carrying.MyCarried.Count > 0)
					{
						Open(radialMenu, instance, (IRadialConfig)(object)new PutDownConfig());
					}
				}
				else if (!AnimalOrders.MayCommand(zdo, localPlayer.GetPlayerID()))
				{
					((Character)localPlayer).Message((MessageType)2, "Only " + zdo.GetString(DexKeys.Tamer, "") + " can give it orders", 0, (Sprite)null, false);
				}
				else
				{
					Open(radialMenu, instance, (IRadialConfig)(object)new WheelConfig(val));
				}
			}
		}

		private static bool IsDown(KeyboardShortcut key)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref key)).MainKey != 0)
			{
				return ((KeyboardShortcut)(ref key)).IsDown();
			}
			return false;
		}

		private static void Open(RadialBase radial, Hud hud, IRadialConfig config)
		{
			try
			{
				_opening = config;
				radial.CanOpen = true;
				radial.Open((IRadialConfig)(object)hud.m_config, (IRadialConfig)null);
			}
			catch (Exception ex)
			{
				Log.Warn("Couldn't open the command wheel: " + ex.Message);
			}
			finally
			{
				_opening = null;
			}
		}

		private static Character Hovered(Player player, out ZDO zdo, out CreatureInfo info)
		{
			zdo = null;
			info = null;
			GameObject hoverObject = ((Humanoid)player).GetHoverObject();
			Character val = (((Object)(object)hoverObject != (Object)null) ? hoverObject.GetComponentInParent<Character>() : null);
			if ((Object)(object)val == (Object)null || val.IsPlayer() || !val.IsTamed() || (Object)(object)val.m_nview == (Object)null || !val.m_nview.IsValid())
			{
				return null;
			}
			zdo = val.m_nview.GetZDO();
			info = CreatureRegistry.Shown(zdo.GetPrefab());
			if (info == null || !HasWheel(info))
			{
				return null;
			}
			return val;
		}

		private static bool HasWheel(CreatureInfo info)
		{
			if (!info.HasCommands)
			{
				if (info.CanCarry)
				{
					return DexConfig.CarryEnabled.Value;
				}
				return false;
			}
			return true;
		}

		[HarmonyPatch(typeof(OpenRadialConfig), "TryOpenNonDefaultRadials")]
		[HarmonyPrefix]
		private static bool OpenOurs(RadialBase radial, ref bool __result)
		{
			if (_opening == null)
			{
				return true;
			}
			radial.Open(_opening, (IRadialConfig)null);
			__result = true;
			return false;
		}

		[HarmonyPatch(typeof(Tameable), "GetHoverText")]
		[HarmonyPostfix]
		private static void HoverText(Tameable __instance, ref string __result)
		{
			//IL_0049: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				if (!string.IsNullOrEmpty(__result) && __instance.IsTamed() && !((Object)(object)__instance.m_nview == (Object)null) && __instance.m_nview.IsValid())
				{
					CreatureInfo creatureInfo = CreatureRegistry.Shown(__instance.m_nview.GetZDO().GetPrefab());
					string text = ((object)DexConfig.CommandKey.Value/*cast due to .constrained prefix*/).ToString();
					if (creatureInfo != null && HasWheel(creatureInfo) && !string.IsNullOrEmpty(text) && !(text == "None"))
					{
						__result = __result + "\n[<color=yellow><b>" + text + "</b></color>] Commands";
					}
				}
			}
			catch
			{
			}
		}

		private static RadialMenuElement Element(string label, string name, string description, bool current, Func<bool> action)
		{
			EmoteElement val = Object.Instantiate<EmoteElement>(RadialData.SO.EmoteElement);
			((RadialMenuElement)val).Name = (current ? (name + " (now)") : name);
			((RadialMenuElement)val).SubTitle = description;
			((RadialMenuElement)val).Description = description;
			((RadialMenuElement)val).Interact = action;
			((RadialMenuElement)val).CloseOnInteract = () => true;
			if ((Object)(object)((RadialMenuElement)val).Icon != (Object)null)
			{
				((Component)((RadialMenuElement)val).Icon).gameObject.SetActive(false);
			}
			AddLabel((RadialMenuElement)(object)val, label, current);
			return (RadialMenuElement)(object)val;
		}

		private static void AddLabel(RadialMenuElement element, string text, bool current)
		{
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: 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_0062: 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_0076: Unknown result type (might be due to invalid IL or missing references)
			if (UiKit.Ready)
			{
				RectTransform obj = UiKit.Child(((Component)element).transform, "VDexLabel");
				Vector2 val = default(Vector2);
				((Vector2)(ref val))..ctor(0.5f, 0.5f);
				obj.anchorMax = val;
				obj.anchorMin = val;
				obj.pivot = new Vector2(0.5f, 0.5f);
				obj.anchoredPosition = Vector2.zero;
				obj.sizeDelta = new Vector2(110f, 40f);
				TextMeshProUGUI obj2 = UiKit.Text(obj, text, UiKit.Font.Label, 18f, current ? UiKit.Orange : Color.white, (TextAlignmentOptions)514);
				((TMP_Text)obj2).enableAutoSizing = true;
				((TMP_Text)obj2).fontSizeMin = 10f;
				((TMP_Text)obj2).fontSizeMax = 18f;
			}
		}
	}
	internal static class DexWindow
	{
		private enum SortMode
		{
			Name,
			Stars,
			Distance
		}

		private sealed class TabRow
		{
			public string Key;

			public GameObject Root;

			public GameObject Selected;

			public Image Icon;

			public TextMeshProUGUI Label;

			public TextMeshProUGUI Count;
		}

		private const float PanelWidth = 1100f;

		private const float PanelHeight = 740f;

		private const float TabHeight = 50f;

		private const string TamingKey = "\u0001taming";

		private const string WithMeKey = "\u0001withme";

		private const string LostKey = "\u0001lost";

		private const string SettingsKey = "\u0001settings";

		private static GameObject _root;

		private static RectTransform _dim;

		private static RectTransform _panel;

		private static RectTransform _tabList;

		private static RectTransform _cardList;

		private static WheelScrollRect _cardScroll;

		private static GameObject _cardArea;

		private static SettingsPage _settings;

		private static TextMeshProUGUI _heading;

		private static TextMeshProUGUI _updated;

		private static TextMeshProUGUI _empty;

		private static TextMeshProUGUI _sortValue;

		private static GameObject _filterBox;

		private static GameObject _allSelected;

		private static GameObject _mineSelected;

		private static readonly List<TabRow> Tabs = new List<TabRow>();

		private static readonly List<AnimalCard> Cards = new List<AnimalCard>();

		private static string _currentTab;

		private static bool _mineOnly;

		private static SortMode _sort = SortMode.Name;

		private static int _releaseMenuFrame = -1;

		private static int _typingFrame = -10;

		private static float _nextTextRefresh;

		private static bool _broken;

		private static bool _openRequested;

		private static bool _dirty;

		private static Sprite _tamingIcon;

		private static bool _tamingIconLooked;

		private const float NearRange = 30f;

		private static readonly float[] Radii = new float[11]
		{
			5f, 10f, 15f, 20f, 30f, 40f, 50f, 75f, 100f, 150f,
			200f
		};

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

		internal static void Init()
		{
			AnimalClient.PanelOpen = () => IsOpen;
			AnimalClient.Updated += delegate
			{
				_dirty = true;
			};
			Carrying.MineChanged += delegate
			{
				_dirty = true;
				if (IsOpen)
				{
					AnimalClient.RequestNow();
				}
			};
			CreatureRegistry.Changed += delegate
			{
				_dirty = true;
			};
		}

		internal static void RequestOpen()
		{
			_openRequested = true;
		}

		private static void Open()
		{
			Menu instance = Menu.instance;
			if ((Object)(object)instance == (Object)null || !UiKit.Ready || _broken)
			{
				return;
			}
			try
			{
				if ((Object)(object)_root == (Object)null)
				{
					Build(((Component)instance).transform);
				}
				_root.transform.SetAsLastSibling();
				_root.SetActive(true);
				FitToScreen();
				instance.m_settingsInstance = _root;
				_releaseMenuFrame = -1;
				_dirty = true;
				AnimalClient.RequestNow();
				Refresh();
			}
			catch (Exception arg)
			{
				_broken = true;
				Log.Error($"The animal panel failed to open; it stays off until the game restarts: {arg}");
				if ((Object)(object)_root != (Object)null)
				{
					Object.Destroy((Object)(object)_root);
				}
				_root = null;
			}
		}

		internal static void Close()
		{
			if (!IsOpen)
			{
				return;
			}
			foreach (AnimalCard card in Cards)
			{
				card.StopRename();
			}
			_settings?.Flush();
			UiKit.Deselect();
			_root.SetActive(false);
			_releaseMenuFrame = Time.frameCount;
		}

		internal static void OnMenuHidden()
		{
			Close();
			ReleaseMenu();
		}

		private static void ReleaseMenu()
		{
			_releaseMenuFrame = -1;
			Menu instance = Menu.instance;
			if ((Object)(object)instance != (Object)null && (Object)(object)_root != (Object)null && (Object)(object)instance.m_settingsInstance == (Object)(object)_root)
			{
				instance.m_settingsInstance = null;
			}
		}

		private static void CloseAll()
		{
			Close();
			ReleaseMenu();
			if ((Object)(object)Menu.instance != (Object)null)
			{
				Menu.instance.Hide();
			}
		}

		internal static void Tick()
		{
			//IL_0088: 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)
			if (_releaseMenuFrame >= 0 && Time.frameCount > _releaseMenuFrame)
			{
				ReleaseMenu();
			}
			if (!IsOpen)
			{
				TickOpening();
			}
			else
			{
				if (KeyCapture.Tick())
				{
					return;
				}
				_settings?.Tick();
				if (IsTyping())
				{
					_typingFrame = Time.frameCount;
				}
				bool flag = Time.frameCount - _typingFrame <= 1 || UnifiedPopup.IsVisible() || UnifiedPopup.WasVisibleThisFrame();
				if (!flag && ZInput.GetKeyDown((KeyCode)27, true))
				{
					Close();
					return;
				}
				if (!flag)
				{
					KeyboardShortcut value = DexConfig.PanelKey.Value;
					if (((KeyboardShortcut)(ref value)).IsDown())
					{
						CloseAll();
						return;
					}
				}
				if (!IsTyping() && (_dirty || Time.unscaledTime >= _nextTextRefresh))
				{
					Refresh();
				}
			}
		}

		private static void TickOpening()
		{
			//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)
			bool openRequested = _openRequested;
			_openRequested = false;
			Menu instance = Menu.instance;
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)instance == (Object)null || (Object)(object)localPlayer == (Object)null)
			{
				return;
			}
			if (!openRequested)
			{
				KeyboardShortcut value = DexConfig.PanelKey.Value;
				if (!((KeyboardShortcut)(ref value)).IsDown())
				{
					return;
				}
			}
			if (((Component)instance.m_root).gameObject.activeSelf)
			{
				if ((Object)(object)instance.m_settingsInstance == (Object)null)
				{
					Open();
				}
			}
			else if (openRequested || (((Character)localPlayer).TakeInput() && !Hud.IsPieceSelectionVisible() && !Hud.InRadial()))
			{
				if (Console.IsVisible())
				{
					((Component)((Terminal)Console.instance).m_chatWindow).gameObject.SetActive(false);
				}
				instance.Show();
				Open();
			}
		}

		private static bool IsTyping()
		{
			GameObject val = (((Object)(object)EventSystem.current != (Object)null) ? EventSystem.current.currentSelectedGameObject : null);
			TMP_InputField val2 = (((Object)(object)val != (Object)null) ? val.GetComponent<TMP_InputField>() : null);
			if ((Object)(object)val2 != (Object)null)
			{
				return val2.isFocused;
			}
			return false;
		}

		private static void Build(Transform parent)
		{
			//IL_009a: 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_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0151: 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_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0193: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_0214: Unknown result type (might be due to invalid IL or missing references)
			//IL_0229: Unknown result type (might be due to invalid IL or missing references)
			//IL_023e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_027b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0284: Unknown result type (might be due to invalid IL or missing references)
			//IL_028e: Expected O, but got Unknown
			//IL_02a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_02bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0301: Unknown result type (might be due to invalid IL or missing references)
			//IL_0338: Unknown result type (might be due to invalid IL or missing references)
			//IL_03c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_03fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_043f: Unknown result type (might be due to invalid IL or missing references)
			//IL_044e: Unknown result type (might be due to invalid IL or missing references)
			//IL_045d: Unknown result type (might be due to invalid IL or missing references)
			//IL_046c: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_04e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_04fc: Unknown result type (might be due to invalid IL or missing references)
			Tabs.Clear();
			Cards.Clear();
			RectTransform obj = UiKit.Child(parent, "VikingDex_Panel").Stretch();
			_root = ((Component)obj).gameObject;
			_root.SetActive(false);
			_dim = UiKit.Child((Transform)(object)obj, "Dim").Stretch();
			((Graphic)((Component)_dim).gameObject.AddComponent<Image>()).color = new Color(0f, 0f, 0f, 0.46f);
			_panel = UiKit.Child((Transform)(object)obj, "Panel").Place(new Vector2(0.5f, 0.5f), new Vector2(0.5f, 0.5f), Vector2.zero, new Vector2(1100f, 740f));
			UiKit.Panel(_panel);
			((TMP_Text)UiKit.Text(UiKit.Child((Transform)(object)_panel, "Title").TopBand(14f, 42f, 0f), "My animals", UiKit.Font.Title, 32f, UiKit.Orange, (TextAlignmentOptions)514)).overflowMode = (TextOverflowModes)0;
			_updated = UiKit.Text(UiKit.Child((Transform)(object)_panel, "Updated").Place(new Vector2(1f, 1f), new Vector2(1f, 0.5f), new Vector2(-44f, -34f), new Vector2(330f, 24f)), "", UiKit.Font.Label, 14f, UiKit.DimText, (TextAlignmentOptions)4100);
			UiKit.Separator(UiKit.Child((Transform)(object)_panel, "HeaderLine").TopBand(62f, 4f, 40f));
			RectTransform obj2 = UiKit.Child((Transform)(object)_panel, "Tabs");
			obj2.anchorMin = new Vector2(0f, 0f);
			obj2.anchorMax = new Vector2(0f, 1f);
			obj2.pivot = new Vector2(0f, 0.5f);
			obj2.offsetMin = new Vector2(36f, 80f);
			obj2.offsetMax = new Vector2(316f, -72f);
			UiKit.Image(obj2, "panel_interior_bkg_128", UiKit.Hex(1709071u, 0.85f));
			_tabList = UiKit.ScrollList(obj2, out var _);
			((LayoutGroup)(VerticalLayoutGroup)((Component)_tabList).GetComponent<LayoutGroup>()).padding = new RectOffset(8, 8, 8, 8);
			RectTransform obj3 = UiKit.Child((Transform)(object)_panel, "Cards");
			obj3.anchorMin = new Vector2(0f, 0f);
			obj3.anchorMax = new Vector2(1f, 1f);
			obj3.offsetMin = new Vector2(330f, 80f);
			obj3.offsetMax = new Vector2(-36f, -72f);
			UiKit.Image(obj3, "panel_interior_bkg_128", UiKit.Hex(1709071u, 0.85f));
			_heading = UiKit.Text(UiKit.Child((Transform)(object)obj3, "Heading").TopBand(8f, 40f, 16f), "", UiKit.Font.Title, 24f, UiKit.Orange, (TextAlignmentOptions)4097);
			BuildFilterAndSort(obj3);
			UiKit.Separator(UiKit.Child((Transform)(object)obj3, "Line").TopBand(54f, 4f, 12f));
			RectTransform obj4 = UiKit.Child((Transform)(object)obj3, "List").Stretch(4f, 4f, 60f, 4f);
			_cardArea = ((Component)obj4).gameObject;
			_cardList = UiKit.ScrollList(obj4, out _cardScroll);
			((HorizontalOrVerticalLayoutGroup)(VerticalLayoutGroup)((Component)_cardList).GetComponent<LayoutGroup>()).spacing = 8f;
			_empty = UiKit.Text(UiKit.Child((Transform)(object)obj4, "Empty").Stretch(40f, 40f, 40f, 40f), "", UiKit.Font.Label, 18f, UiKit.DimText, (TextAlignmentOptions)514);
			((TMP_Text)_empty).textWrappingMode = (TextWrappingModes)1;
			_settings = new SettingsPage(obj3);
			UiKit.Button(UiKit.Child((Transform)(object)_panel, "Close").Place(new Vector2(0.5f, 0f), new Vector2(0.5f, 0.5f), new Vector2(0f, 44f), new Vector2(180f, 46f)), "Close", 16f, Close);
			UiKit.Text(UiKit.Child((Transform)(object)_panel, "Version").Place(new Vector2(1f, 0f), new Vector2(1f, 0.5f), new Vector2(-44f, 44f), new Vector2(200f, 24f)), "VikingDex 1.0.0", UiKit.Font.Label, 13f, UiKit.DimText, (TextAlignmentOptions)4100);
			Log.Info("Animal panel built.");
		}

		private static void BuildFilterAndSort(RectTransform right)
		{
			//IL_0015: 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_0033: 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_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: 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_00dd: 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_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_0167: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c2: 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_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ef: 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)
			RectTransform obj = UiKit.Child((Transform)(object)right, "Filter").Place(new Vector2(1f, 1f), new Vector2(1f, 1f), new Vector2(-16f, -10f), new Vector2(430f, 36f));
			_filterBox = ((Component)obj).gameObject;
			UiKit.TabButton(UiKit.Child((Transform)(object)obj, "All").Place(new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), Vector2.zero, new Vector2(80f, 34f)), "All", delegate
			{
				SetMine(mine: false);
			}, out _allSelected);
			UiKit.TabButton(UiKit.Child((Transform)(object)obj, "Mine").Place(new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(84f, 0f), new Vector2(80f, 34f)), "Mine", delegate
			{
				SetMine(mine: true);
			}, out _mineSelected);
			_sortValue = UiKit.Stepper(UiKit.Child((Transform)(object)obj, "Sort").Place(new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), Vector2.zero, new Vector2(200f, 34f)), delegate(int step)
			{
				int length = Enum.GetValues(typeof(SortMode)).Length;
				_sort = (SortMode)((int)(_sort + step + length) % length);
				_dirty = true;
			});
			UiKit.Text(UiKit.Child((Transform)(object)obj, "SortLabel").Place(new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-206f, 0f), new Vector2(54f, 34f)), "Sort", UiKit.Font.Label, 15f, UiKit.DimText, (TextAlignmentOptions)4100);
		}

		private static void SetMine(bool mine)
		{
			_mineOnly = mine;
			_dirty = true;
		}

		private static TabRow AddTab(string key)
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			//IL_018a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0208: Unknown result type (might be due to invalid IL or missing references)
			//IL_0237: Unknown result type (might be due to invalid IL or missing references)
			//IL_0246: Unknown result type (might be due to invalid IL or missing references)
			//IL_0255: Unknown result type (might be due to invalid IL or missing references)
			//IL_0264: Unknown result type (might be due to invalid IL or missing references)
			//IL_0279: Unknown result type (might be due to invalid IL or missing references)
			//IL_029a: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a4: Expected O, but got Unknown
			//IL_0094: 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)
			RectTransform val = UiKit.Child((Transform)(object)_tabList, "Tab");
			LayoutElement obj = ((Component)val).gameObject.AddComponent<LayoutElement>();
			float minHeight = (obj.preferredHeight = 50f);
			obj.minHeight = minHeight;
			Image val2 = UiKit.Image(val, "button_tab", UiKit.Hex(4864040u));
			Button val3 = ((Component)val).gameObject.AddComponent<Button>();
			((Selectable)val3).targetGraphic = (Graphic)(object)val2;
			Sprite sprite = UiKit.GetSprite("button_tab_hover");
			if ((Object)(object)val2.sprite != (Object)null && (Object)(object)sprite != (Object)null)
			{
				((Selectable)val3).transition = (Transition)2;
				SpriteState spriteState = default(SpriteState);
				((SpriteState)(ref spriteState)).highlightedSprite = sprite;
				((SpriteState)(ref spriteState)).pressedSprite = sprite;
				((SpriteState)(ref spriteState)).selectedSprite = sprite;
				((Selectable)val3).spriteState = spriteState;
			}
			Navigation navigation = ((Selectable)val3).navigation;
			((Navigation)(ref navigation)).mode = (Mode)0;
			((Selectable)val3).navigation = navigation;
			RectTransform val4 = UiKit.Child((Transform)(object)val, "Selected").Stretch();
			((Graphic)UiKit.Image(val4, "button_tab_selected", UiKit.Hex(7032884u))).raycastTarget = false;
			TabRow row = new TabRow
			{
				Key = key,
				Root = ((Component)val).gameObject,
				Selected = ((Component)val4).gameObject
			};
			RectTransform val5 = UiKit.Child((Transform)(object)val, "Icon").Place(new Vector2(0f, 0.5f), new Vector2(0f, 0.5f), new Vector2(8f, 0f), new Vector2(38f, 38f));
			row.Icon = ((Component)val5).gameObject.AddComponent<Image>();
			row.Icon.preserveAspect = true;
			((Graphic)row.Icon).raycastTarget = false;
			RectTransform rt = UiKit.Child((Transform)(object)val, "Label").Stretch(54f, 52f, 2f, 2f);
			row.Label = UiKit.Text(rt, "", UiKit.Font.Label, 17f, UiKit.ButtonText, (TextAlignmentOptions)4097);
			row.Count = UiKit.Text(UiKit.Child((Transform)(object)val, "Count").Place(new Vector2(1f, 0.5f), new Vector2(1f, 0.5f), new Vector2(-10f, 0f), new Vector2(44f, 30f)), "", UiKit.Font.Value, 16f, UiKit.DescriptionText, (TextAlignmentOptions)4100);
			((UnityEvent)val3.onClick).AddListener((UnityAction)delegate
			{
				_currentTab = row.Key;
				((ScrollRect)_cardScroll).verticalNormalizedPosition = 1f;
				_dirty = true;
				UiKit.Deselect();
			});
			Tabs.Add(row);
			return row;
		}

		private static void Refresh()
		{
			_dirty = false;
			_nextTextRefresh = Time.unscaledTime + 1f;
			if ((Object)(object)_root == (Object)null || (Object)(object)ZNet.instance == (Object)null)
			{
				return;
			}
			try
			{
				Fill();
			}
			catch (Exception arg)
			{
				Log.Error($"Animal panel: couldn't show the list: {arg}");
			}
		}

		private static void Fill()
		{
			//IL_00df: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_05a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_06bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0506: Unknown result type (might be due to invalid IL or missing references)
			//IL_050d: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_06ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_06fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_0717: Unknown result type (might be due to invalid IL or missing references)
			//IL_071e: Unknown result type (might be due to invalid IL or missing references)
			bool value = DexConfig.ShowEveryonesAnimals.Value;
			((Component)_filterBox.transform.Find("All")).gameObject.SetActive(value);
			((Component)_filterBox.transform.Find("Mine")).gameObject.SetActive(value);
			bool mine = _mineOnly || !value;
			_allSelected.SetActive(!mine);
			_mineSelected.SetActive(mine);
			((TMP_Text)_sortValue).text = _sort.ToString();
			long me = (((Object)(object)Player.m_localPlayer != (Object)null) ? Player.m_localPlayer.GetPlayerID() : 0);
			Vector3 val = (((Object)(object)Player.m_localPlayer != (Object)null) ? ((Component)Player.m_localPlayer).transform.position : Vector3.zero);
			List<AnimalEntry> source = AnimalClient.Latest.Where((AnimalEntry e) => !mine || e.TamerId == me).ToList();
			List<LostEntry> list = AnimalClient.Lost.Where((LostEntry e) => !mine || e.TamerId == me).ToList();
			List<AnimalEntry> list2 = AnimalClient.Latest.Where((AnimalEntry e) => e.CarrierId == me && me != 0L && e.CarryReason == 1).ToList();
			Dictionary<string, int> dictionary = new Dictionary<string, int>();
			foreach (AnimalEntry item in source.Where((AnimalEntry e) => e.Tamed))
			{
				string key = SpeciesOf(item.Prefab);
				dictionary[key] = ((!dictionary.TryGetValue(key, out var value2)) ? 1 : (value2 + 1));
			}
			List<string> list3 = new List<string> { "\u0001taming" };
			if (list2.Count > 0)
			{
				list3.Add("\u0001withme");
			}
			list3.AddRange(dictionary.Keys.OrderBy<string, string>(TabTitle, StringComparer.CurrentCultureIgnoreCase));
			list3.Add("\u0001lost");
			list3.Add("\u0001settings");
			SyncTabs(list3);
			int count = source.Count((AnimalEntry e) => !e.Tamed);
			foreach (TabRow tab in Tabs)
			{
				if (tab.Key == "\u0001taming")
				{
					SetTab(tab, "Taming now", count, TamingIcon());
				}
				else if (tab.Key == "\u0001withme")
				{
					SetTab(tab, "With me", list2.Count, null);
				}
				else if (tab.Key == "\u0001lost")
				{
					SetTab(tab, "Lost", list.Count, null);
				}
				else if (tab.Key == "\u0001settings")
				{
					SetTab(tab, "Settings", -1, null);
				}
				else
				{
					SetTab(tab, TabTitle(tab.Key), dictionary[tab.Key], CreatureRegistry.SpeciesIcon(tab.Key));
				}
			}
			if (_currentTab == null || !list3.Contains(_currentTab))
			{
				_currentTab = ((dictionary.Count > 0) ? list3.First((string k) => k != "\u0001taming" && k != "\u0001withme") : "\u0001taming");
			}
			foreach (TabRow tab2 in Tabs)
			{
				tab2.Selected.SetActive(tab2.Key == _currentTab);
			}
			bool flag = _currentTab == "\u0001settings";
			_settings.Root.SetActive(flag);
			_cardArea.SetActive(!flag);
			if (flag)
			{
				_filterBox.SetActive(false);
				((TMP_Text)_heading).text = "Settings";
				((TMP_Text)_updated).text = "";
				_settings.Refresh();
				return;
			}
			_filterBox.SetActive(true);
			((TMP_Text)_updated).text = UpdatedText();
			bool canRename = !AnimalClient.LocalOnly && (ZNet.instance.IsServer() || VersionCheck.ServerVersion != null);
			int num = 0;
			if (_currentTab == "\u0001lost")
			{
				((TMP_Text)_heading).text = "Lost animals";
				foreach (LostEntry item2 in SortLost(list, val))
				{
					CreatureRegistry.TryGet(item2.Prefab, out var info);
					CardText text = CardText.ForLost(item2, info, val);
					CardAt(num++).Fill(ZDOID.None, item2.Pos, text, info?.Icon, info?.DisplayName ?? item2.Prefab, "", null);
				}
				((TMP_Text)_empty).text = ((num == 0) ? "No tamed animal has died. May it stay that way." : "");
			}
			else if (_currentTab == "\u0001withme")
			{
				((TMP_Text)_heading).text = "With me";
				foreach (AnimalEntry item3 in Sort(list2, val))
				{
					CreatureRegistry.TryGet(item3.Prefab, out var info2);
					CardText cardText = CardText.ForAnimal(item3, info2, val, canRename);
					cardText.CanPutDown = true;
					CardAt(num++).Fill(item3.Id, item3.Pos, cardText, info2?.Icon, info2?.DisplayName ?? "?", item3.Name, item3);
				}
				((TMP_Text)_empty).text = ((num == 0) ? "You aren't carrying an animal." : "");
			}
			else
			{
				bool tamingTab = _currentTab == "\u0001taming";
				List<AnimalEntry> list4 = source.Where((AnimalEntry e) => (!tamingTab) ? (e.Tamed && SpeciesOf(e.Prefab) == _currentTab) : (!e.Tamed)).ToList();
				((TMP_Text)_heading).text = (tamingTab ? "Taming now" : TabTitle(_currentTab));
				foreach (AnimalEntry item4 in Sort(list4, val))
				{
					CreatureRegistry.TryGet(item4.Prefab, out var info3);
					CardText text2 = CardText.ForAnimal(item4, info3, val, canRename);
					SetControls(text2, item4, info3, val, me);
					CardAt(num++).Fill(item4.Id, item4.Pos, text2, info3?.Icon, info3?.DisplayName ?? "?", item4.Name, item4);
				}
				((TMP_Text)_empty).text = ((num > 0) ? "" : ((AnimalClient.ReceivedAt < 0f) ? "Loading…" : (tamingTab ? "Nobody is taming an animal right now. Feed a wild one and it shows up here." : (mine ? "You haven't tamed an animal yet." : "No tamed animals yet. Tame one and it shows up here."))));
			}
			for (int num2 = 0; num2 < Cards.Count; num2++)
			{
				Cards[num2].Root.SetActive(num2 < num);
			}
		}

		private static string UpdatedText()
		{
			if (AnimalClient.LocalOnly)
			{
				return "This server doesn't run VikingDex: only animals near you.";
			}
			if (AnimalClient.ReceivedAt < 0f)
			{
				return "Loading…";
			}
			int num = Mathf.FloorToInt(Time.unscaledTime - AnimalClient.ReceivedAt);
			if (num > 1)
			{
				return $"Updated {num} s ago";
			}
			return "Up to date";
		}

		private static AnimalCard CardAt(int index)
		{
			while (Cards.Count <= index)
			{
				Cards.Add(new AnimalCard(_cardList, ShowOnMap, delegate(AnimalCard card, string name)
				{
					//IL_0001: Unknown result type (might be due to invalid IL or missing references)
					AnimalClient.Rename(card.Id, name);
				}, StepMode, StepFight, StepRadius, PutDown));
			}
			return Cards[index];
		}

		private static void SyncTabs(List<string> keys)
		{
			if (Tabs.Select((TabRow t) => t.Key).SequenceEqual(keys))
			{
				return;
			}
			foreach (TabRow tab in Tabs)
			{
				Object.Destroy((Object)(object)tab.Root);
			}
			Tabs.Clear();
			foreach (string key in keys)
			{
				AddTab(key);
			}
		}

		private static void SetTab(TabRow tab, string label, int count, Sprite icon)
		{
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Expected O, but got Unknown
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			((TMP_Text)tab.Label).text = label;
			((TMP_Text)tab.Count).text = ((count >= 0) ? count.ToString() : "");
			tab.Icon.sprite = icon;
			((Behaviour)tab.Icon).enabled = (Object)(object)icon != (Object)null;
			RectTransform val = (RectTransform)((TMP_Text)tab.Label).transform;
			val.offsetMin = new Vector2(((Object)(object)icon != (Object)null) ? 54f : 14f, val.offsetMin.y);
		}

		private static Sprite TamingIcon()
		{
			if (!_tamingIconLooked)
			{
				_tamingIconLooked = true;
				_tamingIcon = ((IEnumerable<Sprite>)Resources.FindObjectsOfTypeAll<Sprite>()).FirstOrDefault((Func<Sprite, bool>)((Sprite s) => ((Object)s).name == "heart" || ((Object)s).name == "Heart"));
			}
			return _tamingIcon;
		}

		private static string SpeciesOf(int prefab)
		{
			if (!CreatureRegistry.TryGet(prefab, out var info))
			{
				return "\u0002unknown";
			}
			return info.Species;
		}

		private static string TabTitle(string species)
		{
			if (!(species == "\u0002unknown"))
			{
				return CreatureRegistry.SpeciesTitle(species);
			}
			return "Unknown animals";
		}

		private static IEnumerable<AnimalEntry> Sort(List<AnimalEntry> list, Vector3 me)
		{
			//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)
			return _sort switch
			{
				SortMode.Stars => from e in list
					orderby e.Level descending, NameKey(e.Name, e.Prefab)
					select e, 
				SortMode.Distance => list.OrderBy((AnimalEntry e) => Vector3.Distance(me, e.Pos)), 
				_ => list.OrderBy<AnimalEntry, string>((AnimalEntry e) => NameKey(e.Name, e.Prefab), StringComparer.CurrentCultureIgnoreCase).ThenByDescending((AnimalEntry e) => e.Level), 
			};
		}

		private static IEnumerable<LostEntry> SortLost(List<LostEntry> list, Vector3 me)
		{
			//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)
			return _sort switch
			{
				SortMode.Stars => from e in list
					orderby e.Level descending, e.Time descending
					select e, 
				SortMode.Distance => list.OrderBy((LostEntry e) => Vector3.Distance(me, e.Pos)), 
				_ => list.OrderByDescending((LostEntry e) => e.Time), 
			};
		}

		private static string NameKey(string name, int prefab)
		{
			CreatureInfo info;
			if (string.IsNullOrEmpty(name))
			{
				return "1" + (CreatureRegistry.TryGet(prefab, out info) ? info.DisplayName : "");
			}
			return "0" + name;
		}

		private static AnimalMode ModeOf(AnimalEntry e)
		{
			if (string.IsNullOrEmpty(e.Follow))
			{
				if (!e.Patrol)
				{
					return AnimalMode.Roam;
				}
				return AnimalMode.Stay;
			}
			return AnimalMode.Follow;
		}

		private static void SetControls(CardText text, AnimalEntry e, CreatureInfo info, Vector3 myPos, long me)
		{
			//IL_0040: 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)
			if (e.Tamed && info != null && !((Object)(object)Player.m_localPlayer == (Object)null) && e.CarrierId == 0L && (!DexConfig.OnlyTamerCanCommand.Value || e.TamerId == 0L || e.TamerId == me) && (Vector3.Distance(myPos, e.Pos) <= 30f || ZNet.instance.IsServer() || VersionCheck.ServerVersion != null))
			{
				AnimalMode animalMode = ModeOf(e);
				if (info.CanFollow || info.CanStay || info.CanRoam)
				{
					string playerName = Player.m_localPlayer.GetPlayerName();
					text.ModeText = animalMode switch
					{
						AnimalMode.Stay => "Staying", 
						AnimalMode.Follow => (e.Follow == playerName) ? "Following you" : ("Follows " + e.Follow), 
						_ => "Roaming", 
					};
				}
				if (info.CanFight)
				{
					text.FightText = "Fight: " + ((FightStyle)Mathf.Clamp(e.Fight, 0, 3)/*cast due to .constrained prefix*/).ToString().ToLowerInvariant();
				}
				if (animalMode == AnimalMode.Stay && info.CanStay)
				{
					text.RadiusText = $"Area: {Mathf.RoundToInt(CardText.StayRadius(e, info))} m";
				}
			}
		}

		private static void StepMode(AnimalCard card, int step)
		{
			//IL_0031: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			AnimalEntry entry = card.Entry;
			if (entry == null || (Object)(object)Player.m_localPlayer == (Object)null || !CreatureRegistry.TryGet(entry.Prefab, out var info))
			{
				return;
			}
			bool flag = Vector3.Distance(((Component)Player.m_localPlayer).transform.position, entry.Pos) <= 30f;
			List<AnimalMode> list = new List<AnimalMode>();
			if (info.CanRoam)
			{
				list.Add(AnimalMode.Roam);
			}
			if (info.CanStay)
			{
				list.Add(AnimalMode.Stay);
			}
			if (info.CanFollow && flag)
			{
				list.Add(AnimalMode.Follow);
			}
			if (list.Count == 0)
			{
				return;
			}
			AnimalMode animalMode = ModeOf(entry);
			int num = list.IndexOf(animalMode);
			AnimalMode animalMode2 = ((num < 0) ? list[0] : list[(num + step + list.Count) % list.Count]);
			if (animalMode2 == animalMode)
			{
				if (animalMode == AnimalMode.Follow || list.Count == 1)
				{
					((Character)Player.m_localPlayer).Message((MessageType)2, "Come closer (30 m) to make it follow you", 0, (Sprite)null, false);
				}
				return;
			}
			AnimalOrders.Send(new OrderRequest
			{
				Id = entry.Id,
				Mode = (int)animalMode2
			});
			entry.Follow = ((animalMode2 == AnimalMode.Follow) ? Player.m_localPlayer.GetPlayerName() : "");
			entry.Patrol = animalMode2 == AnimalMode.Stay;
			_dirty = true;
		}

		private static void StepFight(AnimalCard card, int step)
		{
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			AnimalEntry entry = card.Entry;
			if (entry != null)
			{
				int fight = (Mathf.Clamp(entry.Fight, 0, 3) + step + 4) % 4;
				AnimalOrders.Send(new OrderRequest
				{
					Id = entry.Id,
					Fight = fight
				});
				entry.Fight = fight;
				_dirty = true;
			}
		}

		private static void StepRadius(AnimalCard card, int step)
		{
			//IL_00d0: 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)
			AnimalEntry entry = card.Entry;
			if (entry == null || !CreatureRegistry.TryGet(entry.Prefab, out var info))
			{
				return;
			}
			float max = AnimalOrders.MaxRadius(info);
			List<float> list = Radii.Where((float r) => r <= max + 0.01f).ToList();
			if (list.Count == 0)
			{
				list.Add(max);
			}
			float num = CardText.StayRadius(entry, info);
			int num2 = 0;
			for (int num3 = 0; num3 < list.Count; num3++)
			{
				if (Mathf.Abs(list[num3] - num) < Mathf.Abs(list[num2] - num))
				{
					num2 = num3;
				}
			}
			float num4 = list[Mathf.Clamp(num2 + step, 0, list.Count - 1)];
			if (!Mathf.Approximately(num4, num))
			{
				AnimalOrders.Send(new OrderRequest
				{
					Id = entry.Id,
					Radius = num4
				});
				entry.Radius = num4;
				_dirty = true;
			}
		}

		private static void PutDown(AnimalCard card)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			CloseAll();
			Carrying.PutDown(card.Id);
		}

		private static void ShowOnMap(AnimalCard card)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			Vector3 pos = card.Pos;
			string label = card.Label;
			CloseAll();
			MapMarkers.ShowWhere(pos, label);
		}

		private static void FitToScreen()
		{
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_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_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: 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_0057: 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_0077: 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_00ae: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Unknown result type (might be due to invalid IL or missing references)
			Canvas componentInParent = _root.GetComponentInParent<Canvas>();
			if (!((Object)(object)componentInParent == (Object)null))
			{
				RectTransform val = (RectTransform)((Component)componentInParent.rootCanvas).transform;
				Rect rect = val.rect;
				Vector3 position = ((Transform)val).TransformPoint(Vector2.op_Implicit(((Rect)(ref rect)).center));
				Vector3 val2 = default(Vector3);
				((Vector3)(ref val2))..ctor(((Transform)val).lossyScale.x / _root.transform.lossyScale.x, ((Transform)val).lossyScale.y / _root.transform.lossyScale.y, 1f);
				RectTransform dim = _dim;
				RectTransform dim2 = _dim;
				Vector2 val3 = default(Vector2);
				((Vector2)(ref val3))..ctor(0.5f, 0.5f);
				dim2.anchorMax = val3;
				dim.anchorMin = val3;
				_dim.sizeDelta = new Vector2(((Rect)(ref rect)).width * val2.x, ((Rect)(ref rect)).height * val2.y);
				((Transform)_dim).position = position;
				((Transform)_panel).position = position;
				float num = Mathf.Min(new float[3]
				{
					UiKit.WindowScale,
					(((Rect)(ref rect)).width - 40f) / 1100f,
					(((Rect)(ref rect)).height - 40f) / 740f
				});
				if (num > 0f)
				{
					((Transform)_panel).localScale = new Vector3(num, num, 1f);
				}
			}
		}
	}
	internal static class KeyCapture
	{
		private static readonly KeyCode[] Modifiers;

		private static Action<KeyboardShortcut> _done;

		private static Action _cancelled;

		private static int _startFrame;

		private static KeyCode _soloModifier;

		internal static bool IsCapturing => _done != null;

		internal static void Begin(Action<KeyboardShortcut> done, Action cancelled)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			Cancel();
			_done = done;
			_cancelled = cancelled;
			_startFrame = Time.frameCount;
			_soloModifier = (KeyCode)0;
		}

		internal static void Cancel()
		{
			Action cancelled = _cancelled;
			_done = null;
			_cancelled = null;
			cancelled?.Invoke();
		}

		private static void Finish(KeyboardShortcut key)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			Action<KeyboardShortcut> done = _done;
			_done = null;
			_cancelled = null;
			done?.Invoke(key);
		}

		internal static bool Tick()
		{
			//IL_005b: 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_007b: 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_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: Invalid comparison between Unknown and I4
			//IL_0101: 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_008d: Invalid comparison between Unknown and I4
			//IL_0109: 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_0095: Invalid comparison between Unknown and I4
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011f: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ae: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			if (!IsCapturing)
			{
				return false;
			}
			if (Time.frameCount == _startFrame)
			{
				return true;
			}
			IInputSystem current = UnityInput.Current;
			if (current.GetKeyDown((KeyCode)27) || current.GetKeyDown((KeyCode)323) || current.GetKeyDown((KeyCode)324))
			{
				Cancel();
				return true;
			}
			if (current.GetKeyDown((KeyCode)8) || current.GetKeyDown((KeyCode)127))
			{
				Finish(KeyboardShortcut.Empty);
				return true;
			}
			foreach (KeyCode supportedKeyCode in current.SupportedKeyCodes)
			{
				if ((int)supportedKeyCode == 0 || (int)supportedKeyCode >= 330 || (int)supportedKeyCode == 323 || (int)supportedKeyCode == 324)
				{
					continue;
				}
				if (Array.IndexOf(Modifiers, supportedKeyCode) >= 0)
				{
					if (current.GetKeyDown(supportedKeyCode))
					{
						_soloModifier = supportedKeyCode;
					}
				}
				else if (current.GetKeyDown(supportedKeyCode))
				{
					KeyCode[] array = ((IEnumerable<KeyCode>)Modifiers).Where((Func<KeyCode, bool>)current.GetKey).ToArray();
					Finish(new KeyboardShortcut(supportedKeyCode, array));
					return true;
				}
			}
			if ((int)_soloModifier != 0 && current.GetKeyUp(_soloModifier))
			{
				Finish(new KeyboardShortcut(_soloModifier, Array.Empty<KeyCode>()));
			}
			return true;
		}

		internal static string Describe(KeyboardShortcut key)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref key)).MainKey == 0)
			{
				return "None";
			}
			return string.Join(" + ", ((KeyboardShortcut)(ref key)).Modifiers.Select(Name).Concat(new string[1] { Name(((KeyboardShortcut)(ref key)).MainKey) }));
		}

		private unsafe static string Name(KeyCode code)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0003: Invalid comparison between Unknown and I4
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Invalid comparison between Unknown and I4
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Invalid comparison between Unknown and I4
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_009e: Expected I4, but got Unknown
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Invalid comparison between Unknown and I4
			//IL_000d: 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_003a: Expected I4, but got Unknown
			//IL_014c: Unknown result type (might be due to invalid IL or missing references)
			//IL_014f: Invalid comparison between Unknown and I4
			//IL_009e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected I4, but got Unknown
			//IL_0054: 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_0075: Expected I4, but got Unknown
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Invalid comparison between Unknown and I4
			//IL_0151: Unknown result type (might be due to invalid IL or missing references)
			//IL_0154: Invalid comparison between Unknown and I4
			if ((int)code <= 59)
			{
				if ((int)code == 13)
				{
					return "Enter";
				}
				switch (code - 39)
				{
				default:
					if ((int)code != 59)
					{
						break;
					}
					return ";";
				case 6:
					return "-";
				case 0:
					return "'";
				case 5:
					return ",";
				case 7:
					return ".";
				case 8:
					return "/";
				case 1:
				case 2:
				case 3:
				case 4:
					break;
				}
			}
			else if ((int)code <= 96)
			{
				if ((int)code == 61)
				{
					return "=";
				}
				switch (code - 91)
				{
				case 5:
					return "`";
				case 0:
					return "[";
				case 2:
					return "]";
				case 1:
					return "\\";
				}
			}
			else
			{
				switch (code - 305)
				{
				default:
					switch (code - 325)
					{
					case 0:
						return "Middle mouse";
					case 1:
						return "Mouse 4 (Back)";
					case 2:
						return "Mouse 5 (Forward)";
					case 3:
						return "Mouse 6";
					case 4:
						return "Mouse 7";
					}
					break;
				case 1:
					return "Left Ctrl";
				case 0:
					return "Right Ctrl";
				case 5:
					return "Left Cmd";
				case 4:
					return "Right Cmd";
				case 2:
				case 3:
					break;
				}
			}
			string text = ((object)(*(KeyCode*)(&code))/*cast due to .constrained prefix*/).ToString();
			if ((int)code >= 48 && (int)code <= 57)
			{
				return text.Substring(5);
			}
			if (text.StartsWith("Keypad", StringComparison.Ordinal))
			{
				return "Num " + text.Substring(6);
			}
			return SplitWords(text);
		}

		internal static string SplitWords(string text)
		{
			StringBuilder stringBuilder = new StringBuilder(text.Length + 4);
			for (int i = 0; i < text.Length; i++)
			{
				if (i > 0 && char.IsUpper(text[i]) && !char.IsUpper(text[i - 1]))
				{
					stringBuilder.Append(' ');
				}
				stringBuilder.Append(text[i]);
			}
			return stringBuilder.ToString();
		}

		static KeyCapture()
		{
			KeyCode[] array = new KeyCode[8];
			RuntimeHelpers.InitializeArray(array, (RuntimeFieldHandle)/*OpCode not supported: LdMemberToken*/);
			Modifiers = (KeyCode[])(object)array;
		}
	}
	internal static class KeyConflicts
	{
		private static List<(string button, string label)> _gameKeys;

		internal unsafe static List<string> Find(KeyboardShortcut key, ConfigEntryBase self, Func<ConfigEntryBase, string> labelOf)
		{
			//IL_0008: 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_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_0071: Unknown result type (might be due to invalid IL or missing references)
			List<string> list = new List<string>();
			if ((int)((KeyboardShortcut)(ref key)).MainKey == 0)
			{
				return list;
			}
			foreach (KeyValuePair<ConfigDefinition, ConfigEntryBase> item3 in ModConfig.File)
			{
				if (item3.Value != self && !(item3.Value.SettingType != typeof(KeyboardShortcut)) && item3.Value.BoxedValue is KeyboardShortcut val && ((object)(*(KeyboardShortcut*)(&val))/*cast due to .constrained prefix*/).Equals((object?)key))
				{
					list.Add(labelOf(item3.Value) + " (VikingDex)");
				}
			}
			string text = PathOf(((KeyboardShortcut)(ref key)).MainKey);
			if (text != null && ZInput.instance != null)
			{
				foreach (var item4 in GameKeys())
				{
					string item = item4.button;
					string item2 = item4.label;
					ButtonDef buttonDef = ZInput.instance.GetButtonDef(item);
					string text2 = ((buttonDef != null) ? buttonDef.GetActionPath(true) : null);
					if (!string.IsNullOrEmpty(text2) && Normalize(text2) == text && !list.Contains(item2))
					{
						list.Add(item2);
					}
				}
			}
			return list;
		}

		private static string PathOf(KeyCode code)
		{
			//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_0028: Expected I4, but got Unknown
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			switch (code - 323)
			{
			case 0:
				return Normalize("<Mouse>/leftButton");
			case 1:
				return Normalize("<Mouse>/rightButton");
			case 2:
				return Normalize("<Mouse>/middleButton");
			case 3:
				return Normalize("<Mouse>/backButton");
			case 4:
				return Normalize("<Mouse>/forwardButton");
			case 5:
			case 6:
				return null;
			default:
				try
				{
					string text = ZInput.KeyCodeToPath(code, false);
					return (string.IsNullOrEmpty(text) || text.EndsWith("/None", StringComparison.OrdinalIgnoreCase)) ? null : Normalize(text);
				}
				catch (Exception)
				{
					return null;
				}
			}
		}

		private static string Normalize(string path)
		{
			return path.Trim().Replace("<", "").Replace(">", "")
				.TrimStart('/')
				.ToLowerInvariant();
		}

		private static List<(string button, string label)> GameKeys()
		{
			if (_gameKeys != null)
			{
				return _gameKeys;
			}
			_gameKeys = new List<(string, string)>();
			try
			{
				KeyboardMouseSettings val = (((Object)(object)UiKit.SettingsPrefab != (Object)null) ? UiKit.SettingsPrefab.GetComponentInChildren<KeyboardMouseSettings>(true) : null);
				if ((Object)(object)val != (Object)null)
				{
					foreach (KeySetting key in val.m_keys)
					{
						if (!string.IsNullOrEmpty(key.m_keyName) && !((Object)(object)key.m_keyTransform == (Object)null))
						{
							Transform obj = ((Transform)key.m_keyTransform).Find("Label");
							TMP_Text val2 = ((obj != null) ? ((Component)obj).GetComponent<TMP_Text>() : null);
							_gameKeys.Add((key.m_keyName, Translate(((Object)(object)val2 != (Object)null) ? val2.text : null, key.m_keyName)));
						}
					}
				}
			}
			catch (Exception ex)
			{
				Log.Warn("Settings tab: couldn't read the game's controls list: " + ex.Message);
			}
			string[] array = new string[13]
			{
				"Hotbar1", "Hotbar2", "Hotbar3", "Hotbar4", "Hotbar5", "Hotbar6", "Hotbar7", "Hotbar8", "Inventory", "Map",
				"Chat", "Console", "Remove"
			};
			foreach (string button in array)
			{
				if (!_gameKeys.Any(((string button, string label) k) => k.button == button))
				{
					_gameKeys.Add((button, Translate("$settings_" + button.ToLowerInvariant(), button.StartsWith("Hotbar", StringComparison.Ordinal) ? ("Hotbar " + button.Substring(6)) : ((button == "Remove") ? "Remove building piece" : button))));
				}
			}
			Log.Debug($"Settings tab: {_gameKeys.Count} game controls known for the hotkey check.");
			return _gameKeys;
		}

		private static string Translate(string token, string fallback)
		{
			string text = ((token != null && Localization.instance != null) ? Localization.instance.Localize(token) : null)?.Trim().TrimEnd(':').Trim();
			if (!string.IsNullOrEmpty(text) && !text.StartsWith("[") && !text.StartsWith("$"))
			{
				return text;
			}
			return KeyCapture.SplitWords(fallback);
		}
	}
	internal static class MapMarkers
	{
		private sealed class Marker
		{
			public PinData Pin;

			public string Name;
		}

		private const float WhereSeconds = 60f;

		private const float MoveThreshold = 2f;

		private const PinType PinType = (PinType)12;

		private static readonly Dictionary<ZDOID, Marker> Markers = new Dictionary<ZDOID, Marker>();

		private static PinData _where;

		private static float _whereUntil;

		private static Minimap _map;

		private static float _next;

		internal static void ShowWhere(Vector3 pos, string label)
		{
			//IL_0024: 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_0034: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			Minimap instance = Minimap.instance;
			if (!((Object)(object)instance == (Object)null) && !((Object)(object)Player.m_localPlayer == (Object)null))
			{
				RemoveWhere(instance);
				_where = instance.AddPin(pos, (PinType)12, label, false, false, 0L, default(PlatformUserID));
				_where.m_doubleSize = true;
				_where.m_animate = true;
				_whereUntil = Time.unscaledTime + 60f;
				instance.ShowPointOnMap(pos);
			}
		}

		private static void RemoveWhere(Minimap map)
		{
			if (_where != null && (Object)(object)map != (Object)null)
			{
				map.RemovePin(_where);
			}
			_where = null;
		}

		internal static void Tick()
		{
			//IL_010e: 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_0158: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_016a: 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)
			//IL_01ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or miss