Decompiled source of Comfortometer v0.1.2

BepInEx/plugins/Comfortometer.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.U2D;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("Comfortometer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.1.2.0")]
[assembly: AssemblyInformationalVersion("0.1.2+dc609772903968bc1494a861f03968a695d60969")]
[assembly: AssemblyProduct("Comfortometer")]
[assembly: AssemblyTitle("Comfortometer")]
[assembly: AssemblyVersion("0.1.2.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace Comfortometer
{
	[HarmonyPatch(typeof(GameCamera), "UpdateMouseCapture")]
	internal static class GameCamera_UpdateMouseCapture_Arrange
	{
		private static void Postfix()
		{
			if (ComfortPanel.WantsPointer)
			{
				ZCursor.LockState = (CursorLockMode)0;
				ZCursor.Show();
			}
		}
	}
	[HarmonyPatch(typeof(PlayerController), "InInventoryEtc")]
	internal static class PlayerController_InInventoryEtc_Arrange
	{
		private static void Postfix(ref bool __result)
		{
			if (ComfortPanel.WantsPointer)
			{
				__result = true;
			}
		}
	}
	[BepInPlugin("DeathMonger.Comfortometer", "Comfortometer", "0.1.2")]
	[BepInProcess("valheim.exe")]
	public class ComfortometerMod : BaseUnityPlugin
	{
		public const string ModGuid = "DeathMonger.Comfortometer";

		public const string ModName = "Comfortometer";

		public const string ModVersion = "0.1.2";

		internal static ConfigEntry<bool> ModEnabled;

		internal static ConfigEntry<KeyboardShortcut> ToggleKey;

		internal static ConfigEntry<bool> OpenAtStart;

		internal static ConfigEntry<float> ForgetBeyond;

		internal static ConfigEntry<bool> ShowSuperseded;

		internal static ConfigEntry<bool> ShowRestedTime;

		internal static ConfigEntry<bool> ShowRange;

		internal static ConfigEntry<bool> BoldNames;

		internal static ConfigEntry<bool> AutoHeight;

		internal static ConfigEntry<float> FontSize;

		internal static ConfigEntry<string> PanelPosition;

		internal static ConfigEntry<string> PanelSize;

		private Harmony _harmony;

		internal static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_0045: 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_00b1: Expected O, but got Unknown
			//IL_0184: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Expected O, but got Unknown
			//IL_0300: Unknown result type (might be due to invalid IL or missing references)
			//IL_030a: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ModEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Mod Enabled", true, "Master switch. Off hides the panel and ignores the hotkeys. Takes effect immediately.");
			ToggleKey = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("General", "Toggle Panel", new KeyboardShortcut((KeyCode)285, Array.Empty<KeyCode>()), "Shows the comfort panel, which stays up while you move around. While it is up, the same key frees the mouse so you can drag the panel by its title, resize it by the grip in its lower-right corner, or close it with the x; press it again to give the mouse back to the camera. You can still walk around meanwhile. The panel can also be used whenever the cursor is already free, such as with the inventory open.");
			OpenAtStart = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Open At Start", false, "Show the panel as soon as you spawn in, without pressing the toggle key.");
			ForgetBeyond = ((BaseUnityPlugin)this).Config.Bind<float>("General", "Forget Beyond", 30f, new ConfigDescription("A piece you have walked out of range of stays on the list in red until you are this many meters from it. Comfort range itself is 10 m and cannot be changed here.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 200f), Array.Empty<object>()));
			ShowSuperseded = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Show Superseded", false, "Also list pieces in range that give nothing because a better piece of the same group is also in range, such as a stool next to a chair. They are dimmed, with the group named.");
			ShowRestedTime = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Show Rested Time", true, "Show how long the Rested effect lasts at the current comfort level, next to the level.");
			ShowRange = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Show Range", false, "Show each piece's distance against the range it counts within, as in 8.2 / 10 m. The range is the same for every piece: 10 m, fixed by the game.");
			BoldNames = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Bold Names", true, "Draw the piece names in bold.");
			AutoHeight = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Auto Height", true, "The panel grows and shrinks to fit its list. The grip then only changes the width. Off keeps whatever height you drag it to, and a list that does not fit ends in '+N more'.");
			FontSize = ((BaseUnityPlugin)this).Config.Bind<float>("Display", "Font Size", 15f, new ConfigDescription("Text size in the panel. Row height follows it.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(10f, 30f), Array.Empty<object>()));
			PanelPosition = ((BaseUnityPlugin)this).Config.Bind<string>("Display", "Panel Position", "", "Where the panel sits, as x,y from the center of the screen. Written when you drag it; empty means the default spot near the top-right.");
			PanelSize = ((BaseUnityPlugin)this).Config.Bind<string>("Display", "Panel Size", "", "The panel's width,height. Written when you resize it; empty means the default size.");
			ModEnabled.SettingChanged += delegate
			{
				if (!ModEnabled.Value)
				{
					ComfortPanel.Close();
				}
			};
			FontSize.SettingChanged += delegate
			{
				ComfortPanel.Rebuild();
			};
			ShowSuperseded.SettingChanged += delegate
			{
				ComfortPanel.Refresh();
			};
			ShowRestedTime.SettingChanged += delegate
			{
				ComfortPanel.Refresh();
			};
			ShowRange.SettingChanged += delegate
			{
				ComfortPanel.Refresh();
			};
			BoldNames.SettingChanged += delegate
			{
				ComfortPanel.Refresh();
			};
			AutoHeight.SettingChanged += delegate
			{
				ComfortPanel.Refresh();
			};
			_harmony = new Harmony("DeathMonger.Comfortometer");
			_harmony.PatchAll();
			Log.LogInfo((object)"Comfortometer 0.1.2 loaded.");
		}

		private void Update()
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			if (!ModEnabled.Value)
			{
				return;
			}
			ComfortPanel.Tick();
			if ((Object)(object)Player.m_localPlayer == (Object)null)
			{
				return;
			}
			UiBits.ObserveFocus();
			if (Keys.CanTakeInput() && Keys.IsDown(ToggleKey.Value))
			{
				if (!ComfortPanel.IsOpen)
				{
					ComfortPanel.Open();
				}
				else
				{
					ComfortPanel.SetArranging(!ComfortPanel.Arranging);
				}
			}
		}

		private void OnDestroy()
		{
			ComfortPanel.Close();
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	[HarmonyPatch(typeof(Player), "OnSpawned")]
	internal static class Player_OnSpawned_OpenPanel
	{
		private static void Postfix(Player __instance)
		{
			if (!((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && ComfortometerMod.ModEnabled.Value && ComfortometerMod.OpenAtStart.Value)
			{
				ComfortPanel.Open();
			}
		}
	}
	internal static class ComfortPanel
	{
		private sealed class RowUi
		{
			public GameObject Root;

			public TextMeshProUGUI Name;

			public TextMeshProUGUI Comfort;

			public TextMeshProUGUI Distance;
		}

		private const float DefaultW = 250f;

		private const float DefaultH = 190f;

		private const float MinW = 150f;

		private const float MinH = 40f;

		private const float MaxW = 700f;

		private const float MaxH = 1000f;

		private const float Pad = 6f;

		private const float RefreshSeconds = 0.2f;

		private static GameObject _root;

		private static RectTransform _rect;

		private static CanvasGroup _group;

		private static Outline _outline;

		private static TextMeshProUGUI _title;

		private static TextMeshProUGUI _sub;

		private static TextMeshProUGUI _footer;

		private static RectTransform _mover;

		private static RectTransform _grip;

		private static RectTransform _rowsRoot;

		private static Button _closeX;

		private static readonly List<RowUi> _rows = new List<RowUi>();

		private static float _w = 250f;

		private static float _h = 190f;

		private static float _nextRefresh;

		private static ComfortReport _last;

		private static int _failures;

		internal static bool IsOpen { get; private set; }

		internal static bool Arranging { get; private set; }

		internal static bool WantsPointer
		{
			get
			{
				if (IsOpen && Arranging && (Object)(object)_root != (Object)null)
				{
					return (Object)(object)Player.m_localPlayer != (Object)null;
				}
				return false;
			}
		}

		private static float Font
		{
			get
			{
				if (ComfortometerMod.FontSize == null)
				{
					return 15f;
				}
				return ComfortometerMod.FontSize.Value;
			}
		}

		private static float RowH => Mathf.Round(Font * 1.35f);

		private static float TitleH => RowH + 6f;

		private static float ComfortW => Mathf.Round(Font * 2.2f);

		private static float DistanceW => Mathf.Round(Font * (ComfortometerMod.ShowRange.Value ? 5.4f : 3.6f));

		internal static void Open()
		{
			IsOpen = true;
			ComfortScan.Forget();
			_nextRefresh = 0f;
			Tick();
		}

		internal static void Close()
		{
			IsOpen = false;
			SetArranging(on: false);
			if ((Object)(object)_root != (Object)null)
			{
				_root.SetActive(false);
			}
		}

		internal static void SetArranging(bool on)
		{
			if (!(!IsOpen && on))
			{
				Arranging = on;
				ApplyArranging();
			}
		}

		internal static void Rebuild()
		{
			if ((Object)(object)_root != (Object)null)
			{
				Object.Destroy((Object)(object)_root);
			}
			_root = null;
			_rows.Clear();
			_nextRefresh = 0f;
		}

		internal static void Refresh()
		{
			_nextRefresh = 0f;
		}

		internal static void Tick()
		{
			if (!IsOpen)
			{
				return;
			}
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null || (Object)(object)Hud.instance == (Object)null)
			{
				if (Arranging)
				{
					SetArranging(on: false);
				}
				if ((Object)(object)_root != (Object)null)
				{
					_root.SetActive(false);
				}
			}
			else
			{
				if ((Object)(object)_root == (Object)null && !Build())
				{
					return;
				}
				if (!_root.activeSelf)
				{
					_root.SetActive(true);
				}
				bool flag = Arranging || Cursor.visible;
				if (_group.blocksRaycasts != flag)
				{
					_group.blocksRaycasts = flag;
				}
				if (Time.unscaledTime < _nextRefresh)
				{
					return;
				}
				_nextRefresh = Time.unscaledTime + 0.2f;
				try
				{
					_last = ComfortScan.Scan(localPlayer);
					Render(_last);
					_failures = 0;
				}
				catch (Exception arg)
				{
					_failures++;
					ComfortometerMod.Log.LogError((object)$"Comfortometer panel failed to draw ({_failures}): {arg}");
					if (_failures >= 3)
					{
						ComfortometerMod.Log.LogError((object)"Comfortometer: giving up on the panel until it is opened again.");
						Close();
						_failures = 0;
					}
					else
					{
						Rebuild();
					}
				}
			}
		}

		private static bool Build()
		{
			//IL_0061: 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_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0126: Unknown result type (might be due to invalid IL or missing references)
			//IL_0169: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_0240: Unknown result type (might be due to invalid IL or missing references)
			//IL_0245: Unknown result type (might be due to invalid IL or missing references)
			//IL_025b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0266: Unknown result type (might be due to invalid IL or missing references)
			//IL_028c: Unknown result type (might be due to invalid IL or missing references)
			//IL_029c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0328: Unknown result type (might be due to invalid IL or missing references)
			//IL_032d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0343: Unknown result type (might be due to invalid IL or missing references)
			//IL_034e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0369: Unknown result type (might be due to invalid IL or missing references)
			_rows.Clear();
			Hud instance = Hud.instance;
			RectTransform val = (RectTransform)(((Object)(object)instance.m_rootObject != (Object)null) ? /*isinst with value type is only supported in some contexts*/: /*isinst with value type is only supported in some contexts*/);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Image obj = UiBits.Panel((Transform)(object)val, "Comfortometer_Panel", new Color(0.05f, 0.04f, 0.03f, 0.78f));
			_root = ((Component)obj).gameObject;
			_rect = ((Graphic)obj).rectTransform;
			_group = _root.AddComponent<CanvasGroup>();
			_group.blocksRaycasts = false;
			_outline = _root.AddComponent<Outline>();
			((Shadow)_outline).effectDistance = new Vector2(1f, -1f);
			RectTransform rect = _rect;
			RectTransform rect2 = _rect;
			Vector2 val2 = default(Vector2);
			((Vector2)(ref val2))..ctor(0.5f, 0.5f);
			rect2.anchorMax = val2;
			rect.anchorMin = val2;
			_rect.pivot = new Vector2(0.5f, 0.5f);
			_title = UiBits.Text(_root.transform, "Title", "Comfort", Font + 3f, (TextAlignmentOptions)513, UiBits.Gold);
			((TMP_Text)_title).fontStyle = (FontStyles)1;
			_sub = UiBits.Text(_root.transform, "Sub", "", Font - 1f, (TextAlignmentOptions)516, UiBits.Dim);
			_footer = UiBits.Text(_root.transform, "Footer", "", Font - 1f, (TextAlignmentOptions)513, UiBits.Dim);
			GameObject val3 = new GameObject("Rows", new Type[1] { typeof(RectTransform) });
			val3.transform.SetParent(_root.transform, false);
			_rowsRoot = val3.GetComponent<RectTransform>();
			UiBits.Stretch(_rowsRoot);
			GameObject val4 = new GameObject("Grip", new Type[4]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image),
				typeof(UiBits.DragHandle)
			});
			val4.transform.SetParent(_root.transform, false);
			_grip = val4.GetComponent<RectTransform>();
			Image component = val4.GetComponent<Image>();
			component.sprite = UiBits.Grip();
			((Graphic)component).color = new Color(1f, 0.85f, 0.45f, 0.75f);
			((Graphic)component).raycastTarget = true;
			UiBits.DragHandle component2 = val4.GetComponent<UiBits.DragHandle>();
			component2.OnDrag = OnGripDrag;
			component2.OnEnd = SavePlacement;
			val4.SetActive(false);
			GameObject val5 = new GameObject("Mover", new Type[4]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image),
				typeof(UiBits.DragHandle)
			});
			val5.transform.SetParent(_root.transform, false);
			_mover = val5.GetComponent<RectTransform>();
			Image component3 = val5.GetComponent<Image>();
			((Graphic)component3).color = new Color(0f, 0f, 0f, 0f);
			((Graphic)component3).raycastTarget = true;
			UiBits.DragHandle component4 = val5.GetComponent<UiBits.DragHandle>();
			component4.OnDrag = OnMoveDrag;
			component4.OnEnd = SavePlacement;
			_closeX = UiBits.ValheimButton(_root.transform, "CloseX", "x", Close);
			LoadPlacement();
			Layout();
			ApplyArranging();
			return true;
		}

		private static RowUi MakeRow()
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0084: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b9: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("Row", new Type[1] { typeof(RectTransform) });
			val.transform.SetParent((Transform)(object)_rowsRoot, false);
			return new RowUi
			{
				Root = val,
				Name = UiBits.Text(val.transform, "Name", "", Font, (TextAlignmentOptions)513),
				Comfort = UiBits.Text(val.transform, "Comfort", "", Font, (TextAlignmentOptions)516, UiBits.Gold),
				Distance = UiBits.Text(val.transform, "Distance", "", Font - 1f, (TextAlignmentOptions)516, UiBits.Dim)
			};
		}

		private static void Layout()
		{
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0170: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bb: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_root == (Object)null))
			{
				_rect.sizeDelta = new Vector2(_w, _h);
				float num = Mathf.Round(TitleH - 4f);
				float num2 = Mathf.Round(_w * 0.42f);
				UiBits.Place(((TMP_Text)_title).rectTransform, 8f, 2f, num2, TitleH);
				UiBits.Place(((TMP_Text)_sub).rectTransform, 6f + num2, 4f, _w - 12f - num2 - num - 4f, TitleH - 2f);
				UiBits.Place(((Component)_closeX).GetComponent<RectTransform>(), _w - 6f - num + 2f, 2f, num, num);
				float num3 = _w - 12f;
				float num4 = TitleH + 2f;
				for (int i = 0; i < _rows.Count; i++)
				{
					RowUi rowUi = _rows[i];
					UiBits.Place(rowUi.Root.GetComponent<RectTransform>(), 6f, num4 + (float)i * RowH, num3, RowH);
					LayoutRow(rowUi, num3);
				}
				UiBits.Place(_mover, 0f, 0f, _w - num - 6f, TitleH + 2f);
				_grip.anchorMin = new Vector2(1f, 0f);
				_grip.anchorMax = new Vector2(1f, 0f);
				_grip.pivot = new Vector2(1f, 0f);
				_grip.anchoredPosition = new Vector2(-3f, 3f);
				_grip.sizeDelta = new Vector2(14f, 14f);
			}
		}

		private static void LayoutRow(RowUi row, float rowW)
		{
			float num = Mathf.Max(20f, rowW - ComfortW - DistanceW - 8f);
			UiBits.Place(((TMP_Text)row.Name).rectTransform, 2f, 0f, num, RowH);
			UiBits.Place(((TMP_Text)row.Comfort).rectTransform, num + 4f, 0f, ComfortW, RowH);
			UiBits.Place(((TMP_Text)row.Distance).rectTransform, num + ComfortW + 8f, 0f, DistanceW - 4f, RowH);
		}

		private static int Capacity()
		{
			return Mathf.Max(0, Mathf.FloorToInt((_h - TitleH - 2f - 6f) / RowH));
		}

		private static void Render(ComfortReport report)
		{
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_root == (Object)null || report == null)
			{
				return;
			}
			((TMP_Text)_title).text = $"Comfort {report.Level}";
			string text = (ComfortometerMod.ShowRestedTime.Value ? $" · rested {Mathf.RoundToInt(report.RestedSeconds / 60f)} min" : "");
			((TMP_Text)_sub).text = (report.Sheltered ? "sheltered" : "NO SHELTER") + text;
			((Graphic)_sub).color = (report.Sheltered ? UiBits.Dim : UiBits.Red);
			int count = report.Rows.Count;
			if (ComfortometerMod.AutoHeight.Value)
			{
				float num = Mathf.Clamp(TitleH + 2f + (float)Mathf.Max(1, count) * RowH + 6f, 40f, 1000f);
				if (!Mathf.Approximately(num, _h))
				{
					RectTransform rect = _rect;
					rect.anchoredPosition += new Vector2(0f, (0f - (num - _h)) / 2f);
					_h = num;
				}
			}
			int num2 = Capacity();
			int num3 = count;
			string text2 = null;
			if (count == 0)
			{
				text2 = "nothing within 10 m";
				num3 = 0;
			}
			else if (count > num2)
			{
				num3 = Mathf.Max(0, num2 - 1);
				text2 = $"+{count - num3} more";
			}
			while (_rows.Count < num3)
			{
				_rows.Add(MakeRow());
			}
			for (int i = 0; i < _rows.Count; i++)
			{
				RowUi rowUi = _rows[i];
				if (i >= num3)
				{
					rowUi.Root.SetActive(false);
					continue;
				}
				rowUi.Root.SetActive(true);
				Fill(rowUi, report.Rows[i]);
			}
			Layout();
			if (text2 != null && num2 > 0)
			{
				((Component)_footer).gameObject.SetActive(true);
				((TMP_Text)_footer).text = text2;
				UiBits.Place(((TMP_Text)_footer).rectTransform, 8f, TitleH + 2f + (float)num3 * RowH, _w - 12f - 4f, RowH);
			}
			else
			{
				((Component)_footer).gameObject.SetActive(false);
			}
		}

		private static void Fill(RowUi ui, ComfortRow row)
		{
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0101: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: 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_00c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_016e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			string text = row.Name;
			if (row.InRange >= 2)
			{
				text += $" ×{row.InRange}";
			}
			Color color;
			Color color2;
			Color val;
			switch (row.State)
			{
			case RowState.Counted:
				color = UiBits.Body;
				color2 = UiBits.Gold;
				val = UiBits.Dim;
				break;
			case RowState.Superseded:
				if (row.InRange > 0 && !row.Active)
				{
					text += (row.Fireplace ? " (unlit)" : " (off)");
				}
				if (row.Group.Length > 0)
				{
					text = text + " <alpha=#88>(" + row.Group + ")";
				}
				color = (color2 = (val = UiBits.Dim));
				break;
			case RowState.Inactive:
				text += (row.Fireplace ? " (unlit)" : " (off)");
				color = (color2 = (val = UiBits.Red));
				break;
			case RowState.NoShelter:
				color = (color2 = (val = UiBits.Red));
				break;
			default:
				color = (color2 = (val = UiBits.Red));
				break;
			}
			((TMP_Text)ui.Name).text = text;
			((Graphic)ui.Name).color = color;
			((TMP_Text)ui.Name).fontStyle = (FontStyles)(ComfortometerMod.BoldNames.Value ? 1 : 0);
			((TMP_Text)ui.Comfort).text = ((row.Comfort > 0) ? $"+{row.Comfort}" : "");
			((Graphic)ui.Comfort).color = color2;
			((TMP_Text)ui.Distance).text = FormatDistance(row.Distance);
			((Graphic)ui.Distance).color = ((row.Distance >= 10f) ? UiBits.Red : val);
		}

		private static string FormatDistance(float d)
		{
			string text = ((d < 10f) ? $"{d:0.0}" : $"{d:0}");
			if (!ComfortometerMod.ShowRange.Value)
			{
				return text + " m";
			}
			return $"{text} / {10f:0} m";
		}

		private static void ApplyArranging()
		{
			//IL_0049: 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)
			if (!((Object)(object)_root == (Object)null))
			{
				((Shadow)_outline).effectColor = (Arranging ? new Color(1f, 0.85f, 0.45f, 0.95f) : new Color(0.55f, 0.45f, 0.3f, 0.7f));
				((Component)_grip).gameObject.SetActive(Arranging);
				if (_last != null)
				{
					Render(_last);
				}
			}
		}

		private static void OnGripDrag(Vector2 screenDelta)
		{
			//IL_0019: 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_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_008e: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_root == (Object)null))
			{
				float num = CanvasScale();
				float num2 = Mathf.Clamp(_w + screenDelta.x / num, 150f, 700f);
				float num3 = (ComfortometerMod.AutoHeight.Value ? _h : Mathf.Clamp(_h - screenDelta.y / num, 40f, 1000f));
				RectTransform rect = _rect;
				rect.anchoredPosition += new Vector2((num2 - _w) / 2f, (0f - (num3 - _h)) / 2f);
				_w = num2;
				_h = num3;
				if (_last != null)
				{
					Render(_last);
				}
				else
				{
					Layout();
				}
			}
		}

		private static void OnMoveDrag(Vector2 screenDelta)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)_root == (Object)null))
			{
				RectTransform rect = _rect;
				rect.anchoredPosition += screenDelta / CanvasScale();
				ClampToScreen();
			}
		}

		private static float CanvasScale()
		{
			Canvas val = (((Object)(object)_root != (Object)null) ? _root.GetComponentInParent<Canvas>() : null);
			float num = (((Object)(object)val != (Object)null) ? val.rootCanvas.scaleFactor : 1f);
			if (!(num <= 0f))
			{
				return num;
			}
			return 1f;
		}

		private static void ClampToScreen()
		{
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: 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_0080: Unknown result type (might be due to invalid IL or missing references)
			Transform parent = ((Transform)_rect).parent;
			RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
			if (!((Object)(object)val == (Object)null))
			{
				Rect rect = val.rect;
				float num = ((Rect)(ref rect)).width / 2f;
				rect = val.rect;
				float num2 = ((Rect)(ref rect)).height / 2f;
				Vector2 anchoredPosition = _rect.anchoredPosition;
				anchoredPosition.x = Mathf.Clamp(anchoredPosition.x, 0f - num, num);
				anchoredPosition.y = Mathf.Clamp(anchoredPosition.y, 0f - num2, num2);
				_rect.anchoredPosition = anchoredPosition;
			}
		}

		private static void LoadPlacement()
		{
			//IL_006f: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			_w = 250f;
			_h = 190f;
			if (UiBits.TryPair(ComfortometerMod.PanelSize.Value, out var a, out var b))
			{
				_w = Mathf.Clamp(a, 150f, 700f);
				_h = Mathf.Clamp(b, 40f, 1000f);
			}
			if (UiBits.TryPair(ComfortometerMod.PanelPosition.Value, out var a2, out var b2))
			{
				_rect.anchoredPosition = new Vector2(a2, b2);
			}
			else
			{
				Transform parent = ((Transform)_rect).parent;
				RectTransform val = (RectTransform)(object)((parent is RectTransform) ? parent : null);
				float num;
				Rect rect;
				if (!((Object)(object)val != (Object)null))
				{
					num = 960f;
				}
				else
				{
					rect = val.rect;
					num = ((Rect)(ref rect)).width / 2f;
				}
				float num2 = num;
				float num3;
				if (!((Object)(object)val != (Object)null))
				{
					num3 = 540f;
				}
				else
				{
					rect = val.rect;
					num3 = ((Rect)(ref rect)).height / 2f;
				}
				float num4 = num3;
				_rect.anchoredPosition = new Vector2(num2 - _w / 2f - 16f, num4 - _h / 2f - 300f);
			}
			ClampToScreen();
		}

		private static void SavePlacement()
		{
			//IL_0030: 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)
			ComfortometerMod.PanelSize.Value = UiBits.Pair(_w, _h);
			if ((Object)(object)_rect != (Object)null)
			{
				ComfortometerMod.PanelPosition.Value = UiBits.Pair(_rect.anchoredPosition.x, _rect.anchoredPosition.y);
			}
		}
	}
	internal enum RowState
	{
		Counted,
		Superseded,
		Inactive,
		Lost,
		NoShelter
	}
	internal sealed class ComfortRow
	{
		public string Name;

		public string Group;

		public int Comfort;

		public int InRange;

		public bool Active;

		public float Distance;

		public bool Fireplace;

		public RowState State;
	}
	internal sealed class ComfortReport
	{
		public int Level;

		public bool Sheltered;

		public float RestedSeconds;

		public readonly List<ComfortRow> Rows = new List<ComfortRow>();
	}
	internal static class ComfortScan
	{
		private sealed class Known
		{
			public Piece Piece;

			public Vector3 Position;

			public string NameToken;

			public ComfortGroup Group;

			public int Comfort;

			public bool Fireplace;
		}

		internal const float Radius = 10f;

		private static readonly List<Known> _known = new List<Known>();

		private static readonly List<Piece> _nearby = new List<Piece>();

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

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

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

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

		private static float _baseTtl = -1f;

		private static float _ttlPerLevel;

		internal static void Forget()
		{
			_known.Clear();
		}

		internal static ComfortReport Scan(Player player)
		{
			//IL_0017: 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_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_0100: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: 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_00d1: Unknown result type (might be due to invalid IL or missing references)
			//IL_0179: Unknown result type (might be due to invalid IL or missing references)
			//IL_017c: 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_0174: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01db: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			ComfortReport comfortReport = new ComfortReport();
			if ((Object)(object)player == (Object)null)
			{
				return comfortReport;
			}
			Vector3 position = ((Component)player).transform.position;
			float num = Mathf.Max(10f, ComfortometerMod.ForgetBeyond.Value);
			comfortReport.Sheltered = player.InShelter();
			comfortReport.Level = SE_Rested.CalculateComfortLevel(player);
			comfortReport.RestedSeconds = RestedSeconds(comfortReport.Level);
			_nearby.Clear();
			Piece.GetAllComfortPiecesInRadius(position, 10f, _nearby);
			foreach (Piece item in _nearby)
			{
				if (!((Object)(object)item == (Object)null))
				{
					Known known = Find(item);
					if (known == null)
					{
						known = new Known
						{
							Piece = item,
							NameToken = (item.m_name ?? ""),
							Group = item.m_comfortGroup,
							Fireplace = ((Object)(object)((Component)item).GetComponent<Fireplace>() != (Object)null)
						};
						_known.Add(known);
					}
					known.Position = ((Component)item).transform.position;
					known.Comfort = item.m_comfort;
				}
			}
			for (int num2 = _known.Count - 1; num2 >= 0; num2--)
			{
				Known known2 = _known[num2];
				if ((Object)(object)known2.Piece != (Object)null)
				{
					known2.Position = ((Component)known2.Piece).transform.position;
				}
				if (Vector3.Distance(position, known2.Position) >= num)
				{
					_known.RemoveAt(num2);
				}
			}
			_byName.Clear();
			_maxActive.Clear();
			_maxFull.Clear();
			foreach (Known item2 in _known)
			{
				float num3 = Vector3.Distance(position, item2.Position);
				int num4;
				int num5;
				if ((Object)(object)item2.Piece != (Object)null)
				{
					num4 = ((num3 < 10f) ? 1 : 0);
					if (num4 != 0)
					{
						num5 = item2.Piece.GetComfort();
						goto IL_0214;
					}
				}
				else
				{
					num4 = 0;
				}
				num5 = 0;
				goto IL_0214;
				IL_0214:
				int num6 = num5;
				if (!_byName.TryGetValue(item2.NameToken, out var value))
				{
					value = new ComfortRow
					{
						Name = ((Localization.instance != null) ? Localization.instance.Localize(item2.NameToken) : item2.NameToken),
						Group = (((int)item2.Group == 0) ? "" : ((object)Unsafe.As<ComfortGroup, ComfortGroup>(ref item2.Group)/*cast due to .constrained prefix*/).ToString().ToLowerInvariant()),
						Distance = num3,
						Fireplace = item2.Fireplace
					};
					_byName[item2.NameToken] = value;
					_maxActive[item2.NameToken] = 0;
					_maxFull[item2.NameToken] = 0;
				}
				if (num3 < value.Distance)
				{
					value.Distance = num3;
				}
				if (num4 != 0)
				{
					value.InRange++;
				}
				if (num6 > _maxActive[item2.NameToken])
				{
					_maxActive[item2.NameToken] = num6;
				}
				if (item2.Comfort > _maxFull[item2.NameToken])
				{
					_maxFull[item2.NameToken] = item2.Comfort;
				}
			}
			foreach (KeyValuePair<string, ComfortRow> item3 in _byName)
			{
				ComfortRow value2 = item3.Value;
				int num7 = _maxActive[item3.Key];
				value2.Active = num7 > 0;
				if (num7 > 0)
				{
					value2.State = RowState.Counted;
					value2.Comfort = num7;
				}
				else
				{
					value2.State = ((value2.InRange > 0) ? RowState.Inactive : RowState.Lost);
					value2.Comfort = _maxFull[item3.Key];
				}
			}
			List<ComfortRow> list = new List<ComfortRow>(_byName.Values);
			list.Sort(VanillaOrder);
			ComfortRow comfortRow = null;
			_countedGroups.Clear();
			foreach (ComfortRow item4 in list)
			{
				if (item4.State != RowState.Counted)
				{
					continue;
				}
				if (comfortRow != null && item4.Group.Length > 0 && item4.Group == comfortRow.Group)
				{
					item4.State = RowState.Superseded;
					continue;
				}
				comfortRow = item4;
				if (item4.Group.Length > 0)
				{
					_countedGroups.Add(item4.Group);
				}
				if (!comfortReport.Sheltered)
				{
					item4.State = RowState.NoShelter;
				}
			}
			for (int num8 = list.Count - 1; num8 >= 0; num8--)
			{
				ComfortRow comfortRow2 = list[num8];
				if (comfortRow2.Group.Length != 0 && _countedGroups.Contains(comfortRow2.Group))
				{
					if (comfortRow2.State == RowState.Inactive)
					{
						comfortRow2.State = RowState.Superseded;
					}
					else if (comfortRow2.State == RowState.Lost)
					{
						list.RemoveAt(num8);
					}
				}
			}
			list.Sort(DisplayOrder);
			foreach (ComfortRow item5 in list)
			{
				if (item5.State != RowState.Superseded || ComfortometerMod.ShowSuperseded.Value)
				{
					comfortReport.Rows.Add(item5);
				}
			}
			return comfortReport;
		}

		private static Known Find(Piece piece)
		{
			foreach (Known item in _known)
			{
				if ((Object)(object)item.Piece == (Object)(object)piece)
				{
					return item;
				}
			}
			return null;
		}

		private static int VanillaOrder(ComfortRow x, ComfortRow y)
		{
			int num = string.CompareOrdinal(x.Group, y.Group);
			if (num != 0)
			{
				return num;
			}
			if (x.Comfort != y.Comfort)
			{
				return y.Comfort.CompareTo(x.Comfort);
			}
			return string.CompareOrdinal(y.Name, x.Name);
		}

		private static int DisplayOrder(ComfortRow x, ComfortRow y)
		{
			int num = Rank(x.State);
			int num2 = Rank(y.State);
			if (num != num2)
			{
				return num.CompareTo(num2);
			}
			if (num >= 2)
			{
				return x.Distance.CompareTo(y.Distance);
			}
			return VanillaOrder(x, y);
		}

		private static int Rank(RowState s)
		{
			switch (s)
			{
			case RowState.Counted:
			case RowState.NoShelter:
				return 0;
			case RowState.Superseded:
				return 1;
			case RowState.Inactive:
				return 2;
			default:
				return 3;
			}
		}

		private static float RestedSeconds(int level)
		{
			if (_baseTtl < 0f)
			{
				SE_Rested val = (SE_Rested)(((Object)(object)ObjectDB.instance != (Object)null) ? /*isinst with value type is only supported in some contexts*/: null);
				if ((Object)(object)val == (Object)null)
				{
					return 300f + (float)(level - 1) * 60f;
				}
				_baseTtl = val.m_baseTTL;
				_ttlPerLevel = val.m_TTLPerComfortLevel;
			}
			return _baseTtl + (float)(level - 1) * _ttlPerLevel;
		}
	}
	internal static class Keys
	{
		internal static bool IsDown(KeyboardShortcut shortcut)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			if ((int)((KeyboardShortcut)(ref shortcut)).MainKey == 0)
			{
				return false;
			}
			if (!ZInput.GetKeyDown(((KeyboardShortcut)(ref shortcut)).MainKey, true))
			{
				return false;
			}
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
			{
				if (!ZInput.GetKey(modifier, true))
				{
					return false;
				}
			}
			return true;
		}

		internal static bool ModifierHeld(KeyboardShortcut shortcut)
		{
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			foreach (KeyCode modifier in ((KeyboardShortcut)(ref shortcut)).Modifiers)
			{
				if (ZInput.GetKey(modifier, true))
				{
					return true;
				}
			}
			return false;
		}

		internal static bool CanTakeInput()
		{
			if (Console.IsVisible() || TextInput.IsVisible() || Menu.IsActive())
			{
				return false;
			}
			if ((Object)(object)Chat.instance != (Object)null && Chat.instance.HasFocus())
			{
				return false;
			}
			if ((Object)(object)Minimap.instance != (Object)null && Minimap.InTextInput())
			{
				return false;
			}
			if (BuildSearchFocused())
			{
				return false;
			}
			if (UiBits.AnyFieldFocused())
			{
				return false;
			}
			return true;
		}

		private static bool BuildSearchFocused()
		{
			Hud instance = Hud.instance;
			if ((Object)(object)instance == (Object)null || (Object)(object)instance.m_buildUi == (Object)null)
			{
				return false;
			}
			try
			{
				return instance.m_buildUi.SearchFieldFocused;
			}
			catch
			{
				return false;
			}
		}
	}
	internal static class UiBits
	{
		internal sealed class DragHandle : MonoBehaviour, IDragHandler, IEventSystemHandler, IEndDragHandler
		{
			public Action<Vector2> OnDrag;

			public Action OnEnd;

			void IDragHandler.OnDrag(PointerEventData eventData)
			{
				//IL_000c: Unknown result type (might be due to invalid IL or missing references)
				OnDrag?.Invoke(eventData.delta);
			}

			void IEndDragHandler.OnEndDrag(PointerEventData eventData)
			{
				OnEnd?.Invoke();
			}
		}

		internal static readonly Color Gold = new Color(1f, 0.85f, 0.45f);

		internal static readonly Color Dim = new Color(0.62f, 0.6f, 0.56f);

		internal static readonly Color Body = new Color(0.95f, 0.92f, 0.85f);

		internal static readonly Color Red = new Color(1f, 0.36f, 0.3f);

		internal static readonly Color Green = new Color(0.55f, 0.9f, 0.5f);

		private static TMP_FontAsset _font;

		private static Material _fontMaterial;

		private static int _anyFocusedFrame = -1000;

		private static int _observedFrame = -1;

		private static bool _typingNow;

		private static Sprite _grip;

		internal static void EnsureFont()
		{
			if ((Object)(object)_font != (Object)null)
			{
				return;
			}
			TMP_FontAsset[] array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
			foreach (TMP_FontAsset val in array)
			{
				if (!((Object)(object)val == (Object)null))
				{
					string name = ((Object)val).name;
					if (name.IndexOf("AveriaSerifLibre", StringComparison.OrdinalIgnoreCase) >= 0 && name.IndexOf("Bold", StringComparison.OrdinalIgnoreCase) < 0)
					{
						_font = val;
						_fontMaterial = ((TMP_Asset)val).material;
						return;
					}
				}
			}
			TMP_Text val2 = null;
			if ((Object)(object)MessageHud.instance != (Object)null)
			{
				val2 = MessageHud.instance.m_messageCenterText;
			}
			else if ((Object)(object)TextInput.instance != (Object)null && (Object)(object)TextInput.instance.m_topic != (Object)null)
			{
				val2 = TextInput.instance.m_topic;
			}
			if ((Object)(object)val2 != (Object)null && (Object)(object)val2.font != (Object)null)
			{
				_font = val2.font;
				_fontMaterial = val2.fontSharedMaterial;
				return;
			}
			TMP_FontAsset val3 = null;
			array = Resources.FindObjectsOfTypeAll<TMP_FontAsset>();
			foreach (TMP_FontAsset val4 in array)
			{
				if (!((Object)(object)val4 == (Object)null))
				{
					if ((Object)(object)val3 == (Object)null)
					{
						val3 = val4;
					}
					if (((Object)val4).name.IndexOf("Averia", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						val3 = val4;
						break;
					}
				}
			}
			if (!((Object)(object)val3 == (Object)null))
			{
				_font = val3;
				_fontMaterial = ((TMP_Asset)val3).material;
			}
		}

		internal static bool AnyFieldFocused()
		{
			ObserveFocus();
			if (!_typingNow)
			{
				return Time.frameCount - _anyFocusedFrame <= 2;
			}
			return true;
		}

		internal static void ObserveFocus()
		{
			if (_observedFrame != Time.frameCount)
			{
				_observedFrame = Time.frameCount;
				EventSystem current = EventSystem.current;
				GameObject val = (((Object)(object)current != (Object)null) ? current.currentSelectedGameObject : null);
				_typingNow = (Object)(object)val != (Object)null && IsTyping(val);
				if (_typingNow)
				{
					_anyFocusedFrame = Time.frameCount;
				}
			}
		}

		private static bool IsTyping(GameObject go)
		{
			TMP_InputField component = go.GetComponent<TMP_InputField>();
			if ((Object)(object)component != (Object)null && component.isFocused)
			{
				return true;
			}
			InputField component2 = go.GetComponent<InputField>();
			if ((Object)(object)component2 != (Object)null)
			{
				return component2.isFocused;
			}
			return false;
		}

		internal static void Place(RectTransform rt, float x, float y, float w, float h)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: 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_0051: Unknown result type (might be due to invalid IL or missing references)
			rt.anchorMin = new Vector2(0f, 1f);
			rt.anchorMax = new Vector2(0f, 1f);
			rt.pivot = new Vector2(0f, 1f);
			rt.anchoredPosition = new Vector2(x, 0f - y);
			rt.sizeDelta = new Vector2(w, h);
		}

		internal static void Stretch(RectTransform rt, float pad = 0f)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			rt.anchorMin = Vector2.zero;
			rt.anchorMax = Vector2.one;
			rt.pivot = new Vector2(0.5f, 0.5f);
			rt.offsetMin = new Vector2(pad, pad);
			rt.offsetMax = new Vector2(0f - pad, 0f - pad);
		}

		internal static TextMeshProUGUI Text(Transform parent, string name, string text, float size, TextAlignmentOptions align, Color? color = null)
		{
			//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_0032: 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_008e: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			EnsureFont();
			GameObject val = new GameObject(name, new Type[2]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer)
			});
			val.SetActive(false);
			val.transform.SetParent(parent, false);
			TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)_font != (Object)null)
			{
				((TMP_Text)val2).font = _font;
			}
			if ((Object)(object)_fontMaterial != (Object)null)
			{
				((TMP_Text)val2).fontSharedMaterial = _fontMaterial;
			}
			((TMP_Text)val2).text = text ?? "";
			((TMP_Text)val2).fontSize = size;
			((TMP_Text)val2).alignment = align;
			((Graphic)val2).color = (Color)(((??)color) ?? Body);
			((Graphic)val2).raycastTarget = false;
			((TMP_Text)val2).overflowMode = (TextOverflowModes)1;
			((TMP_Text)val2).textWrappingMode = (TextWrappingModes)0;
			((TMP_Text)val2).richText = true;
			val.SetActive(true);
			return val2;
		}

		internal static Image Panel(Transform parent, string name, Color color)
		{
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[3]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image)
			});
			val.transform.SetParent(parent, false);
			Image component = val.GetComponent<Image>();
			((Graphic)component).color = color;
			((Graphic)component).raycastTarget = true;
			return component;
		}

		internal static Sprite Grip()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Expected O, but got Unknown
			//IL_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: 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)
			if ((Object)(object)_grip != (Object)null)
			{
				return _grip;
			}
			Texture2D val = new Texture2D(24, 24, (TextureFormat)4, false);
			Color32[] array = (Color32[])(object)new Color32[576];
			for (int i = 0; i < 24; i++)
			{
				for (int j = 0; j < 24; j++)
				{
					int num = j + (23 - i);
					bool flag = num >= 21 && (num - 21) % 6 < 2;
					array[i * 24 + j] = new Color32(byte.MaxValue, byte.MaxValue, byte.MaxValue, (byte)(flag ? 255u : 0u));
				}
			}
			val.SetPixels32(array);
			val.Apply(false, true);
			((Texture)val).filterMode = (FilterMode)1;
			((Texture)val).wrapMode = (TextureWrapMode)1;
			((Object)val).hideFlags = (HideFlags)61;
			_grip = Sprite.Create(val, new Rect(0f, 0f, 24f, 24f), new Vector2(0.5f, 0.5f), 100f);
			((Object)_grip).hideFlags = (HideFlags)61;
			return _grip;
		}

		internal static Button ValheimButton(Transform parent, string name, string label, Action onClick)
		{
			//IL_0048: 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_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: 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_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0123: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_0185: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b2: Expected O, but got Unknown
			GameObject val = new GameObject(name, new Type[4]
			{
				typeof(RectTransform),
				typeof(CanvasRenderer),
				typeof(Image),
				typeof(Button)
			});
			val.transform.SetParent(parent, false);
			Image component = val.GetComponent<Image>();
			Sprite val2 = FindSprite("button");
			if ((Object)(object)val2 != (Object)null)
			{
				component.sprite = val2;
				component.type = (Type)1;
				component.pixelsPerUnitMultiplier = 2f;
			}
			else
			{
				((Graphic)component).color = new Color(0.25f, 0.2f, 0.15f, 0.9f);
			}
			((Graphic)component).raycastTarget = true;
			Button component2 = val.GetComponent<Button>();
			((Selectable)component2).transition = (Transition)1;
			ColorBlock colors = default(ColorBlock);
			((ColorBlock)(ref colors)).normalColor = new Color(0.824f, 0.824f, 0.824f, 1f);
			((ColorBlock)(ref colors)).highlightedColor = new Color(1.3f, 1.3f, 1.3f, 1f);
			((ColorBlock)(ref colors)).pressedColor = new Color(0.537f, 0.556f, 0.556f, 1f);
			((ColorBlock)(ref colors)).selectedColor = new Color(0.824f, 0.824f, 0.824f, 1f);
			((ColorBlock)(ref colors)).disabledColor = new Color(0.566f, 0.566f, 0.566f, 0.502f);
			((ColorBlock)(ref colors)).colorMultiplier = 1f;
			((ColorBlock)(ref colors)).fadeDuration = 0.1f;
			((Selectable)component2).colors = colors;
			((Selectable)component2).targetGraphic = (Graphic)(object)component;
			if (onClick != null)
			{
				((UnityEvent)component2.onClick).AddListener((UnityAction)delegate
				{
					onClick();
				});
			}
			TextMeshProUGUI obj = Text(val.transform, "Label", label, 14f, (TextAlignmentOptions)514, (Color?)new Color(1f, 0.631f, 0.235f));
			((TMP_Text)obj).fontStyle = (FontStyles)1;
			Stretch(((TMP_Text)obj).rectTransform);
			return component2;
		}

		private static Sprite FindSprite(string name)
		{
			SpriteAtlas[] array = Resources.FindObjectsOfTypeAll<SpriteAtlas>();
			foreach (SpriteAtlas val in array)
			{
				if (!((Object)(object)val == (Object)null) && !(((Object)val).name != "UIAtlas"))
				{
					Sprite sprite = val.GetSprite(name);
					if ((Object)(object)sprite != (Object)null)
					{
						return sprite;
					}
				}
			}
			Sprite[] array2 = Resources.FindObjectsOfTypeAll<Sprite>();
			foreach (Sprite val2 in array2)
			{
				if ((Object)(object)val2 != (Object)null && ((Object)val2).name == name)
				{
					return val2;
				}
			}
			return null;
		}

		internal static bool TryPair(string text, out float a, out float b)
		{
			a = 0f;
			b = 0f;
			if (string.IsNullOrEmpty(text))
			{
				return false;
			}
			string[] array = text.Split(new char[1] { ',' });
			if (array.Length == 2 && float.TryParse(array[0].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out a))
			{
				return float.TryParse(array[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out b);
			}
			return false;
		}

		internal static string Pair(float a, float b)
		{
			return $"{Mathf.RoundToInt(a)},{Mathf.RoundToInt(b)}";
		}
	}
}