Decompiled source of ComfortHelper v1.0.0

ComfortHelper.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Koendertjh.Shared;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
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("ComfortHelper")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+a45c570d17c512d77d75166ff42bc1dee72ef243")]
[assembly: AssemblyProduct("ComfortHelper")]
[assembly: AssemblyTitle("ComfortHelper")]
[assembly: AssemblyVersion("1.0.0.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 Koendertjh.Shared
{
	internal static class AchievementStats
	{
		private static readonly Dictionary<object, KeyValuePair<int, HashSet<string>>> s_keys = new Dictionary<object, KeyValuePair<int, HashSet<string>>>();

		internal static Achievement Find(string id)
		{
			if ((Object)(object)Achievements.m_instance == (Object)null)
			{
				return null;
			}
			foreach (AchievementList achievementList in Achievements.m_instance.m_achievementLists)
			{
				foreach (Achievement achievement in achievementList.m_achievements)
				{
					if ((Object)(object)achievement != (Object)null && achievement.m_id == id)
					{
						return achievement;
					}
				}
			}
			return null;
		}

		internal static PlayerStats StatsFor(Achievement achievement)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			Game instance = Game.instance;
			PlayerProfile val = ((instance != null) ? instance.GetPlayerProfile() : null);
			if (val == null || (Object)(object)achievement == (Object)null)
			{
				return null;
			}
			return val.m_playerStats[achievement.m_difficultyRequirement];
		}

		internal static HashSet<string> Keys(List<DictStatRequirement> triggers)
		{
			//IL_0040: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			if (triggers == null)
			{
				return new HashSet<string>();
			}
			if (s_keys.TryGetValue(triggers, out var value) && value.Key == triggers.Count)
			{
				return value.Value;
			}
			HashSet<string> hashSet = new HashSet<string>();
			foreach (DictStatRequirement trigger in triggers)
			{
				hashSet.Add(trigger.m_stat);
			}
			s_keys[triggers] = new KeyValuePair<int, HashSet<string>>(triggers.Count, hashSet);
			return hashSet;
		}

		internal static HashSet<string> Keys(List<EnemyStatRequirement> triggers)
		{
			//IL_0040: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			if (triggers == null)
			{
				return new HashSet<string>();
			}
			if (s_keys.TryGetValue(triggers, out var value) && value.Key == triggers.Count)
			{
				return value.Value;
			}
			HashSet<string> hashSet = new HashSet<string>();
			foreach (EnemyStatRequirement trigger in triggers)
			{
				hashSet.Add(trigger.m_stat);
			}
			s_keys[triggers] = new KeyValuePair<int, HashSet<string>>(triggers.Count, hashSet);
			return hashSet;
		}

		internal static bool Has(Dictionary<string, float> stats, string key)
		{
			if (stats != null && stats.TryGetValue(key, out var value))
			{
				return value >= 1f;
			}
			return false;
		}

		internal static int CountDone(HashSet<string> keys, Dictionary<string, float> stats)
		{
			int num = 0;
			foreach (string key in keys)
			{
				if (Has(stats, key))
				{
					num++;
				}
			}
			return num;
		}
	}
}
namespace ComfortHelper
{
	internal class Suggestion
	{
		public Piece Piece;

		public int Gain;

		public Piece Replaces;
	}
	internal class ComfortReport
	{
		public bool InShelter;

		public int Current;

		public int BestKnown;

		public int Locked;

		public float MaxReached;

		public readonly List<Suggestion> Suggestions = new List<Suggestion>();
	}
	internal static class Comfort
	{
		private const float Radius = 10f;

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

		private static List<Piece> s_comfortPrefabs;

		private static ZNetScene s_scene;

		private static readonly string[] GroupNames = Enum.GetNames(typeof(ComfortGroup));

		internal static string GroupOf(Piece piece)
		{
			//IL_0001: 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)
			if ((int)piece.m_comfortGroup == 0)
			{
				return piece.m_name;
			}
			return GroupNames[piece.m_comfortGroup];
		}

		internal static Dictionary<string, Piece> BestNearby(Vector3 position)
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			Dictionary<string, Piece> dictionary = new Dictionary<string, Piece>();
			Nearby(position, dictionary, null);
			return dictionary;
		}

		internal static void Nearby(Vector3 position, Dictionary<string, Piece> best, HashSet<string> names)
		{
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			s_nearby.Clear();
			Piece.GetAllComfortPiecesInRadius(position, 10f, s_nearby);
			foreach (Piece item in s_nearby)
			{
				names?.Add(item.m_name);
				if (best != null)
				{
					string key = GroupOf(item);
					if (!best.TryGetValue(key, out var value) || item.GetComfort() > value.GetComfort())
					{
						best[key] = item;
					}
				}
			}
		}

		internal static ComfortReport Build(Player player)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			ComfortReport comfortReport = new ComfortReport
			{
				InShelter = player.InShelter(),
				Current = SE_Rested.CalculateComfortLevel(player),
				MaxReached = MaxComfort()
			};
			Dictionary<string, Piece> dictionary = BestNearby(((Component)player).transform.position);
			Dictionary<string, Piece> dictionary2 = new Dictionary<string, Piece>();
			Dictionary<string, int> dictionary3 = new Dictionary<string, int>();
			foreach (Piece item in ComfortPrefabs())
			{
				string key = GroupOf(item);
				if (!dictionary3.TryGetValue(key, out var value) || item.m_comfort > value)
				{
					dictionary3[key] = item.m_comfort;
				}
				if (player.IsRecipeKnown(item.m_name) && (!dictionary2.TryGetValue(key, out var value2) || item.m_comfort > value2.m_comfort))
				{
					dictionary2[key] = item;
				}
			}
			int num = 0;
			foreach (KeyValuePair<string, Piece> item2 in dictionary2)
			{
				num += item2.Value.m_comfort;
				dictionary.TryGetValue(item2.Key, out var value3);
				int num2 = item2.Value.m_comfort - (((Object)(object)value3 != (Object)null) ? value3.GetComfort() : 0);
				if (num2 > 0)
				{
					comfortReport.Suggestions.Add(new Suggestion
					{
						Piece = item2.Value,
						Gain = num2,
						Replaces = value3
					});
				}
			}
			comfortReport.BestKnown = 2 + num;
			comfortReport.Locked = dictionary3.Sum((KeyValuePair<string, int> p) => p.Value) - num;
			comfortReport.Suggestions.Sort((Suggestion a, Suggestion b) => b.Gain.CompareTo(a.Gain));
			return comfortReport;
		}

		private static float MaxComfort()
		{
			PlayerStats val = AchievementStats.StatsFor(AchievementStats.Find("GrindComfort"));
			if (val == null || !val.m_stats.TryGetValue((PlayerStatType)132, out var value))
			{
				return 0f;
			}
			return value;
		}

		private static List<Piece> ComfortPrefabs()
		{
			if (s_comfortPrefabs != null && (Object)(object)s_scene == (Object)(object)ZNetScene.instance)
			{
				return s_comfortPrefabs;
			}
			s_scene = ZNetScene.instance;
			s_comfortPrefabs = new List<Piece>();
			if ((Object)(object)s_scene == (Object)null || (Object)(object)ObjectDB.instance == (Object)null)
			{
				return s_comfortPrefabs;
			}
			HashSet<string> hashSet = new HashSet<string>();
			foreach (GameObject item in ObjectDB.instance.m_items)
			{
				PieceTable val = ((!((Object)(object)item != (Object)null)) ? null : item.GetComponent<ItemDrop>()?.m_itemData.m_shared.m_buildPieces);
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				foreach (GameObject piece in val.m_pieces)
				{
					Piece val2 = (((Object)(object)piece != (Object)null) ? piece.GetComponent<Piece>() : null);
					if ((Object)(object)val2 != (Object)null && val2.m_comfort > 0 && hashSet.Add(val2.m_name))
					{
						s_comfortPrefabs.Add(val2);
					}
				}
			}
			return s_comfortPrefabs;
		}

		internal static string Describe(Suggestion suggestion)
		{
			string arg = Localization.instance.Localize(suggestion.Piece.m_name);
			if (!((Object)(object)suggestion.Replaces == (Object)null))
			{
				return $"+{suggestion.Gain} {arg} (instead of {Localization.instance.Localize(suggestion.Replaces.m_name)})";
			}
			return $"+{suggestion.Gain} {arg}";
		}
	}
	internal static class ComfortGroups
	{
		internal unsafe static string Name(ComfortGroup group)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Expected I4, but got Unknown
			return (int)group switch
			{
				1 => "Fires", 
				2 => "Beds", 
				3 => "Banners", 
				4 => "Seats", 
				5 => "Tables", 
				6 => "Rugs", 
				7 => "Displays", 
				8 => "Decorations", 
				9 => "Garlands", 
				10 => "Lanterns", 
				11 => "Leisure", 
				0 => "Each counts", 
				_ => ((object)(*(ComfortGroup*)(&group))/*cast due to .constrained prefix*/).ToString(), 
			};
		}
	}
	internal sealed class ComfortPieceList : IPieceList
	{
		private readonly ComfortGroup[] _groups = (ComfortGroup[])Enum.GetValues(typeof(ComfortGroup));

		private readonly List<int> _availableTags = new List<int>();

		public string DisplayName { get; }

		public bool ShowTags => true;

		public bool CanCustomizeTags => false;

		public int TagCount => _availableTags.Count;

		public int TagSeparatorIndex => -1;

		public ComfortPieceList(string displayName)
		{
			DisplayName = displayName;
		}

		public string GetTagDisplayName(int index)
		{
			int num = (int)_groups[_availableTags[index]];
			string text = ComfortGroups.Name((ComfortGroup)num);
			int num2 = NearbyState.GroupComfort((ComfortGroup)num);
			if (num2 <= 0)
			{
				return text;
			}
			return $"<color=#7CFC7C>{text} +{num2}</color>";
		}

		public int GetTagIdByIndex(int index)
		{
			return _availableTags[index];
		}

		public void UpdateAvailableTags(PieceTable pieceTable)
		{
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			HashSet<ComfortGroup> hashSet = new HashSet<ComfortGroup>();
			foreach (Piece availablePiece in pieceTable.m_availablePieces)
			{
				if (availablePiece.m_comfort > 0)
				{
					hashSet.Add(availablePiece.m_comfortGroup);
				}
			}
			_availableTags.Clear();
			for (int i = 0; i < _groups.Length; i++)
			{
				if (_groups[i] && hashSet.Contains(_groups[i]))
				{
					_availableTags.Add(i);
				}
			}
			int item = Array.IndexOf(_groups, (ComfortGroup)0);
			if (hashSet.Contains((ComfortGroup)0))
			{
				_availableTags.Add(item);
			}
		}

		public void GetAvailablePiecesWithTag(int tagId, PieceTable pieceTable, IList<Piece> resultOut)
		{
			foreach (Piece item in from p in pieceTable.m_availablePieces
				where p.m_comfort > 0 && (tagId < 0 || tagId >= _groups.Length || (int)p.m_comfortGroup == (int)_groups[tagId])
				orderby p.m_comfort descending
				select p)
			{
				resultOut.Add(item);
			}
		}
	}
	internal static class NearbyState
	{
		private static Dictionary<string, Piece> s_best = new Dictionary<string, Piece>();

		private static HashSet<string> s_names = new HashSet<string>();

		private static Dictionary<string, Piece> s_nextBest = new Dictionary<string, Piece>();

		private static HashSet<string> s_nextNames = new HashSet<string>();

		private static float s_nextUpdate;

		internal static int Version { get; private set; }

		internal static bool Update(Player player, bool force = false)
		{
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			if (!force && Time.time < s_nextUpdate)
			{
				return false;
			}
			s_nextUpdate = Time.time + 1f;
			s_nextBest.Clear();
			s_nextNames.Clear();
			Comfort.Nearby(((Component)player).transform.position, s_nextBest, s_nextNames);
			bool num = !s_nextNames.SetEquals(s_names) || !SameCounting(s_nextBest, s_best);
			Dictionary<string, Piece> dictionary = s_nextBest;
			Dictionary<string, Piece> dictionary2 = s_best;
			s_best = dictionary;
			s_nextBest = dictionary2;
			HashSet<string> hashSet = s_nextNames;
			HashSet<string> hashSet2 = s_names;
			s_names = hashSet;
			s_nextNames = hashSet2;
			if (num)
			{
				Version++;
			}
			return num;
		}

		private static bool SameCounting(Dictionary<string, Piece> a, Dictionary<string, Piece> b)
		{
			if (a.Count != b.Count)
			{
				return false;
			}
			foreach (KeyValuePair<string, Piece> item in a)
			{
				if (!b.TryGetValue(item.Key, out var value) || value.m_name != item.Value.m_name)
				{
					return false;
				}
			}
			return true;
		}

		internal static bool IsHere(Piece piece)
		{
			return s_names.Contains(piece.m_name);
		}

		internal static bool Counts(Piece piece)
		{
			if (s_best.TryGetValue(Comfort.GroupOf(piece), out var value))
			{
				return value.m_name == piece.m_name;
			}
			return false;
		}

		internal static Piece Counting(Piece piece)
		{
			if (!s_best.TryGetValue(Comfort.GroupOf(piece), out var value))
			{
				return null;
			}
			return value;
		}

		internal unsafe static int GroupComfort(ComfortGroup group)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			if ((int)group == 0)
			{
				return s_best.Values.Where((Piece p) => (int)p.m_comfortGroup == 0).Sum((Piece p) => p.GetComfort());
			}
			if (!s_best.TryGetValue(((object)(*(ComfortGroup*)(&group))/*cast due to .constrained prefix*/).ToString(), out var value))
			{
				return 0;
			}
			return value.GetComfort();
		}
	}
	[HarmonyPatch]
	internal static class ComfortTabPatches
	{
		private const string CheckName = "ComfortHelperCheck";

		private static readonly Color Green = new Color(0.45f, 0.95f, 0.45f);

		private static readonly Color Grey = new Color(0.62f, 0.62f, 0.62f);

		private static readonly FieldRef<BuildUi, RectTransform> TabContainerRef = AccessTools.FieldRefAccess<BuildUi, RectTransform>("m_tabContainer");

		private static readonly FieldRef<BuildUi, TabHandler> TabHandlerRef = AccessTools.FieldRefAccess<BuildUi, TabHandler>("m_tabHandler");

		private static readonly FieldRef<BuildUi, List<IPieceList>> PieceListsRef = AccessTools.FieldRefAccess<BuildUi, List<IPieceList>>("m_pieceLists");

		private static readonly FieldRef<BuildUi, int> AvailablePieceCountRef = AccessTools.FieldRefAccess<BuildUi, int>("m_availablePieceCount");

		private static readonly FieldRef<BuildUi, int> CurrentPieceListRef = AccessTools.FieldRefAccess<BuildUi, int>("m_currentPieceList");

		private static readonly FieldRef<BuildUi, List<BuildUiPieceButton>> PieceButtonsRef = AccessTools.FieldRefAccess<BuildUi, List<BuildUiPieceButton>>("m_pieceButtons");

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

		private static int s_hoverVersion = -1;

		[HarmonyPrefix]
		[HarmonyPatch(typeof(BuildUi), "Awake")]
		private static void BeforeAwake(BuildUi __instance, out bool __state)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_007c: Expected O, but got Unknown
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0090: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c2: 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_0112: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Expected O, but got Unknown
			//IL_0122: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_0134: Expected O, but got Unknown
			__state = false;
			if (!ComfortHelperPlugin.ComfortTab.Value)
			{
				return;
			}
			RectTransform val = TabContainerRef.Invoke(__instance);
			TabHandler val2 = TabHandlerRef.Invoke(__instance);
			if ((Object)(object)val == (Object)null || (Object)(object)val2 == (Object)null || ((Transform)val).childCount < 2 || val2.m_tabs.Count != ((Transform)val).childCount)
			{
				ComfortHelperPlugin.Log.LogWarning((object)"Build menu tabs have an unexpected layout; the Comfort tab is disabled.");
				return;
			}
			RectTransform val3 = (RectTransform)((Transform)val).GetChild(((Transform)val).childCount - 1);
			RectTransform val4 = (RectTransform)((Transform)val).GetChild(((Transform)val).childCount - 2);
			RectTransform val5 = Object.Instantiate<RectTransform>(val3, (Transform)(object)val);
			((Object)val5).name = "ComfortHelper_ComfortTab";
			if ((Object)(object)((Component)val).GetComponent<LayoutGroup>() == (Object)null)
			{
				val5.anchoredPosition = val3.anchoredPosition + (val3.anchoredPosition - val4.anchoredPosition);
			}
			TMP_Text[] componentsInChildren = ((Component)val5).GetComponentsInChildren<TMP_Text>(true);
			for (int i = 0; i < componentsInChildren.Length; i++)
			{
				componentsInChildren[i].text = ComfortHelperPlugin.TabName.Value;
			}
			Button component = ((Component)val5).GetComponent<Button>();
			component.onClick = new ButtonClickedEvent();
			val2.m_tabs.Add(new Tab
			{
				m_button = component
			});
			__state = true;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BuildUi), "Awake")]
		private static void AfterAwake(BuildUi __instance, bool __state)
		{
			if (__state)
			{
				PieceListsRef.Invoke(__instance).Add((IPieceList)(object)new ComfortPieceList(ComfortHelperPlugin.TabName.Value));
			}
		}

		private static bool ComfortTabShown(BuildUi buildUi)
		{
			List<IPieceList> list = PieceListsRef.Invoke(buildUi);
			int num = CurrentPieceListRef.Invoke(buildUi);
			if (num >= 0 && num < list.Count)
			{
				return list[num] is ComfortPieceList;
			}
			return false;
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(BuildUi), "UpdatePieceButtons")]
		private static void AfterUpdatePieceButtons(BuildUi __instance)
		{
			//IL_00cc: 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_00d1: 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)
			Player localPlayer = Player.m_localPlayer;
			bool flag = (Object)(object)localPlayer != (Object)null && (ComfortTabShown(__instance) || ComfortHelperPlugin.ChecksInAllTabs.Value);
			if (flag)
			{
				NearbyState.Update(localPlayer, force: true);
			}
			foreach (BuildUiPieceButton item in PieceButtonsRef.Invoke(__instance))
			{
				Piece piece = item.Piece;
				bool flag2 = flag && (Object)(object)piece != (Object)null && piece.m_comfort > 0 && NearbyState.IsHere(piece);
				Transform val = ((Component)item).transform.Find("ComfortHelperCheck");
				if ((Object)(object)val == (Object)null)
				{
					if (!flag2)
					{
						continue;
					}
					val = CreateCheck(((Component)item).transform);
				}
				((Component)val).gameObject.SetActive(flag2);
				if (flag2)
				{
					Color color = (NearbyState.Counts(piece) ? Green : Grey);
					Image[] componentsInChildren = ((Component)val).GetComponentsInChildren<Image>(true);
					for (int i = 0; i < componentsInChildren.Length; i++)
					{
						((Graphic)componentsInChildren[i]).color = color;
					}
				}
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Hud), "Update")]
		private static void AfterHudUpdate()
		{
			BuildUi val = (((Object)(object)Hud.instance != (Object)null) ? Hud.instance.m_buildUi : null);
			Player localPlayer = Player.m_localPlayer;
			if (!((Object)(object)val == (Object)null) && !((Object)(object)localPlayer == (Object)null) && ((Behaviour)val).isActiveAndEnabled && (ComfortTabShown(val) || ComfortHelperPlugin.ChecksInAllTabs.Value) && NearbyState.Update(localPlayer))
			{
				AvailablePieceCountRef.Invoke(val) = -1;
			}
		}

		private static Transform CreateCheck(Transform button)
		{
			//IL_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Expected O, but got Unknown
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: 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_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: 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_005b: 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_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Expected O, but got Unknown
			//IL_00ef: Expected O, but got Unknown
			GameObject val = new GameObject("ComfortHelperCheck", new Type[1] { typeof(RectTransform) });
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent(button, false);
			Vector2 val3 = default(Vector2);
			((Vector2)(ref val3))..ctor(1f, 1f);
			val2.anchorMax = val3;
			val2.anchorMin = val3;
			val2.pivot = new Vector2(1f, 1f);
			val2.anchoredPosition = new Vector2(-3f, -3f);
			val2.sizeDelta = new Vector2(18f, 16f);
			((Transform)val2).SetAsLastSibling();
			Bar(val2, new Vector2(5f, 6f), new Vector2(9f, 4f), -45f);
			Bar(val2, new Vector2(11f, 8f), new Vector2(15f, 4f), 50f);
			val.SetActive(false);
			return (Transform)val2;
		}

		private static void Bar(RectTransform parent, Vector2 center, Vector2 size, float angle)
		{
			//IL_0032: Unknown result type (might be due to invalid IL or missing references)
			//IL_0037: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: 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_004a: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005e: 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_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_007a: 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_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: 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_00d0: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject("bar", new Type[3]
			{
				typeof(RectTransform),
				typeof(Image),
				typeof(Outline)
			});
			RectTransform val2 = (RectTransform)val.transform;
			((Transform)val2).SetParent((Transform)(object)parent, false);
			Vector2 anchorMin = (val2.anchorMax = Vector2.zero);
			val2.anchorMin = anchorMin;
			val2.pivot = new Vector2(0.5f, 0.5f);
			val2.anchoredPosition = center;
			val2.sizeDelta = size;
			((Transform)val2).localRotation = Quaternion.Euler(0f, 0f, angle);
			((Graphic)val.GetComponent<Image>()).raycastTarget = false;
			Outline component = val.GetComponent<Outline>();
			((Shadow)component).effectColor = new Color(0f, 0f, 0f, 0.85f);
			((Shadow)component).effectDistance = new Vector2(1f, -1f);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Hud), "SetupPieceInfo")]
		private static void AfterSetupPieceInfo(Hud __instance, Piece piece)
		{
			Player localPlayer = Player.m_localPlayer;
			if (ComfortHelperPlugin.HoverInfo.Value && !((Object)(object)piece == (Object)null) && piece.m_comfort > 0 && !((Object)(object)localPlayer == (Object)null))
			{
				NearbyState.Update(localPlayer);
				if (s_hoverVersion != NearbyState.Version)
				{
					s_hoverTexts.Clear();
					s_hoverVersion = NearbyState.Version;
				}
				if (!s_hoverTexts.TryGetValue(piece.m_name, out var value))
				{
					value = (s_hoverTexts[piece.m_name] = HoverText(piece));
				}
				TMP_Text pieceDescription = __instance.m_pieceDescription;
				pieceDescription.text += value;
			}
		}

		private static string HoverText(Piece piece)
		{
			//IL_001e: 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)
			Localization instance = Localization.instance;
			string text = $"\n\n<color=#ffb347>Comfort +{piece.m_comfort}</color> ";
			text += (((int)piece.m_comfortGroup == 0) ? "(counts once, next to everything else)" : ("(" + ComfortGroups.Name(piece.m_comfortGroup) + ": only the best one nearby counts)"));
			Piece val = NearbyState.Counting(piece);
			if ((Object)(object)val == (Object)null)
			{
				return text + $"\nNothing like it within 10 m: <color=#7CFC7C>+{piece.m_comfort} here</color>.";
			}
			if (val.m_name == piece.m_name)
			{
				return text + "\n<color=#7CFC7C>Already counts here.</color>";
			}
			if (piece.m_comfort > val.GetComfort())
			{
				return text + $"\n{instance.Localize(val.m_name)} counts here now: <color=#7CFC7C>+{piece.m_comfort - val.GetComfort()} more</color> with this one.";
			}
			return text + "\n" + instance.Localize(val.m_name) + " already counts here; this one adds nothing.";
		}
	}
	internal static class Commands
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static ConsoleEvent <0>__Run;
		}

		public static void Register()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Expected O, but got Unknown
			try
			{
				object obj = <>O.<0>__Run;
				if (obj == null)
				{
					ConsoleEvent val = Run;
					<>O.<0>__Run = val;
					obj = (object)val;
				}
				new ConsoleCommand("comfort", "ComfortHelper: your comfort here and the pieces that would raise it", (ConsoleEvent)obj, false, false, false, false, false, false, (ConsoleOptionsFetcher)null, false, false, false);
			}
			catch (Exception ex)
			{
				ComfortHelperPlugin.Log.LogWarning((object)("Couldn't add console commands: " + ex.Message));
			}
		}

		private static void Run(ConsoleEventArgs args)
		{
			Player localPlayer = Player.m_localPlayer;
			if ((Object)(object)localPlayer == (Object)null)
			{
				Say(args, "ComfortHelper: load into a world with a character first.");
				return;
			}
			ComfortReport comfortReport = Comfort.Build(localPlayer);
			Say(args, $"ComfortHelper: comfort here {comfortReport.Current}, best so far {comfortReport.MaxReached:0} " + "(Comfort is King needs 20).");
			if (!comfortReport.InShelter)
			{
				Say(args, "  You are not under a roof: pieces only count in a shelter.");
			}
			Say(args, $"  With the pieces you know, the most you can reach is {comfortReport.BestKnown}." + ((comfortReport.Locked > 0) ? $" Pieces you haven't unlocked yet add up to {comfortReport.Locked} more." : ""));
			if (comfortReport.Suggestions.Count == 0)
			{
				Say(args, "  Nothing you know would raise it here.");
				return;
			}
			Say(args, "  Within 10 m, add:");
			foreach (Suggestion suggestion in comfortReport.Suggestions)
			{
				Say(args, "    " + Comfort.Describe(suggestion));
			}
		}

		private static void Say(ConsoleEventArgs args, string text)
		{
			if ((Object)(object)args?.Context != (Object)null)
			{
				args.Context.AddString(text);
			}
			else
			{
				ComfortHelperPlugin.Log.LogInfo((object)text);
			}
		}
	}
	[BepInPlugin("com.koendertjh.comforthelper", "ComfortHelper", "1.0.0")]
	public class ComfortHelperPlugin : BaseUnityPlugin
	{
		public const string ModGuid = "com.koendertjh.comforthelper";

		public const string ModName = "ComfortHelper";

		public const string ModVersion = "1.0.0";

		internal static ManualLogSource Log;

		internal static ConfigEntry<bool> RestingMessage;

		internal static ConfigEntry<float> MessageCooldown;

		internal static ConfigEntry<int> MaxSuggestions;

		internal static ConfigEntry<bool> ComfortTab;

		internal static ConfigEntry<string> TabName;

		internal static ConfigEntry<bool> ChecksInAllTabs;

		internal static ConfigEntry<bool> HoverInfo;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_0059: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Expected O, but got Unknown
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012e: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			RestingMessage = ((BaseUnityPlugin)this).Config.Bind<bool>("1 - General", "RestingMessage", true, "When you start resting, show which known pieces would raise your comfort here.");
			MessageCooldown = ((BaseUnityPlugin)this).Config.Bind<float>("1 - General", "MessageCooldown", 600f, new ConfigDescription("Seconds before the resting message shows again.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 3600f), Array.Empty<object>()));
			MaxSuggestions = ((BaseUnityPlugin)this).Config.Bind<int>("1 - General", "MaxSuggestions", 4, new ConfigDescription("Pieces listed in the resting message (the /comfort command lists all).", (AcceptableValueBase)(object)new AcceptableValueRange<int>(1, 20), Array.Empty<object>()));
			ComfortTab = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Build menu", "ComfortTab", true, "A Comfort tab in the build menu with every comfort piece, one category per comfort group. Needs a restart.");
			TabName = ((BaseUnityPlugin)this).Config.Bind<string>("2 - Build menu", "TabName", "Comfort", "Name of the tab. Needs a restart.");
			ChecksInAllTabs = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Build menu", "ChecksInAllTabs", false, "Also show the check marks on comfort pieces in the other build menu tabs.");
			HoverInfo = ((BaseUnityPlugin)this).Config.Bind<bool>("2 - Build menu", "HoverInfo", true, "The description of a comfort piece shows its comfort, its group and what it would add where you stand.");
			_harmony = new Harmony("com.koendertjh.comforthelper");
			_harmony.PatchAll(typeof(ComfortHelperPlugin).Assembly);
			Commands.Register();
		}

		private void OnDestroy()
		{
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}
	}
	[HarmonyPatch(typeof(Player), "UpdateEnvStatusEffects")]
	internal static class RestingMessage
	{
		private static bool s_wasResting;

		private static float s_lastShown = -10000f;

		private static void Postfix(Player __instance)
		{
			if ((Object)(object)__instance != (Object)(object)Player.m_localPlayer)
			{
				return;
			}
			bool flag = ((Character)__instance).GetSEMan().HaveStatusEffect(SEMan.s_statusEffectResting);
			bool num = flag && !s_wasResting;
			s_wasResting = flag;
			if (!num || !ComfortHelperPlugin.RestingMessage.Value || Time.time - s_lastShown < ComfortHelperPlugin.MessageCooldown.Value)
			{
				return;
			}
			s_lastShown = Time.time;
			ComfortReport comfortReport = Comfort.Build(__instance);
			string text = $"Comfort {comfortReport.Current} (best so far {comfortReport.MaxReached:0}, Comfort is King needs 20)";
			if (comfortReport.Suggestions.Count > 0)
			{
				text = text + "\nTo raise it: " + string.Join(", ", comfortReport.Suggestions.Take(ComfortHelperPlugin.MaxSuggestions.Value).Select(Comfort.Describe));
				if (comfortReport.Suggestions.Count > ComfortHelperPlugin.MaxSuggestions.Value)
				{
					text += ", ... (/comfort lists all)";
				}
			}
			((Character)__instance).Message((MessageType)1, text, 0, (Sprite)null, false);
		}
	}
	internal static class PluginInfo
	{
		public const string Version = "1.0.0";
	}
}