Decompiled source of ZenHoverItem v0.2.15

plugins\ZenHoverItem.dll

Decompiled a day ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using Jotunn.Utils;
using Microsoft.CodeAnalysis;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using Zen.Config;
using Zen.Lib;
using Zen.Logging;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyTitle("ZenHoverItem")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("ZenHoverItem")]
[assembly: AssemblyCopyright("Copyright \ufffd  2021")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("e3243d22-4307-4008-ba36-9f326008cde5")]
[assembly: AssemblyFileVersion("0.0.1.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("0.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

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

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

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.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 ZenHoverItem
{
	internal static class Configs
	{
		[Flags]
		public enum FuelMeterType
		{
			None = 0,
			Fireplace = 1,
			SmelterFuel = 2,
			SmelterOre = 4,
			All = -1
		}

		public static readonly ConfigEntry<bool> ShowHoverIcons;

		public static readonly ConfigEntry<FuelMeterType> ShowHoverIconForFuel;

		public static readonly ConfigEntry<FuelMeterType> ShowFuelMeter;

		public static readonly ConfigEntry<bool> AdjustFuelBurnRate;

		public static readonly ConfigEntry<bool> ShowFuelDays;

		public static readonly ConfigEntry<int> ContainerMaxIcons;

		public static readonly ConfigEntry<bool> ArmorStandShowHoverIcons;

		public static readonly ConfigEntry<bool> ArmorStandShowHoverText;

		public static readonly ConfigEntry<bool> ShowItemDescription;

		public static readonly ConfigEntry<bool> ShowShieldGenMeter;

		static Configs()
		{
			ShowHoverIcons = Config.Define<bool>(true, "General", "Show Hover Icons", true, "Display hover icons on the crosshair for important pieces such as containers? (Global)");
			ShowHoverIconForFuel = Config.Define<FuelMeterType>(true, "Fuel", "Show Fuel Hover Icon", FuelMeterType.All, "Show the hover icon for fuelable things such as fireplaces, torches, and smelters");
			ShowFuelMeter = Config.Define<FuelMeterType>(true, "Fuel", "Show Fuel Meter", FuelMeterType.SmelterOre, "Show the fuel meter");
			ShowFuelDays = Config.Define<bool>(true, "Fuel", "Show Fuel Days", true, "Show the number of game days of fuel remaining on Fireplaces. (Vanilla: false)\r\nThis helps you understand the different dynamics of the various light sources and realize they are not just cosmetic.\r\nThe game itself does not provide a clock. Vikings had no clocks. The only unit of time they had was days.\r\nInstall ZenCompass to see the passage of time.\r\nNOTE: This is very important when using ZenRaids as you need to know how long before the fire burns out and monsters spawn.\r\nAlso, in a mod like Seasons you need to know if you have enough fuel to last the winter.");
			AdjustFuelBurnRate = Config.Define<bool>(true, "Fuel", "Adjust Fuel Burn Rate", true, "This will adjust the fuel burn rate on fireplaces so the amount of days remaining when full are easily recognizable numbers. (Vanilla: false)\r\nVanilla day lengths and fuel burn times are not evenly divisible resulting in awkward max fuel days.\r\nThis adjusts the burn rate per unit of fuel so they divide evenly with the day length.\r\nThe result is that max fuel days will be easily recognizable days 20, 25, 50, 60 instead of 22, 28, 56, 67.\r\nNOTE: If you are using the Seasons mod and have the fireplaceDrainMultipliers set (they are on by default), they will create uneven max fuel days.\r\nThis is because calculations can no longer be computed linearly for all days and instead are based on per season variable burn rates.\r\nIf you want nice easily recognizable max days while using Seasons then the easiest thing to do is set the per season burn rate multipliers back to 1.\r\nTo edit Seasons config: Copy the Spring.js, Summer.js, Fall.js, and Winter.js files from the Seasons/DefaultSettings config folder up one level.\r\nThen edit each file and set the fireplaceDrainMultiplier to 1.0");
			ContainerMaxIcons = Config.Define<int>(true, "Containers", "Container Max Icons", 4, Config.AcceptRange<int>(0, 5), "How many icons to display on containers?");
			ArmorStandShowHoverIcons = Config.Define<bool>(true, "Armor Stand", "Show Hover Icons", false, "Display the hover icons for armor stands");
			ArmorStandShowHoverText = Config.Define<bool>(true, "Armor Stand", "Show Hover Text", true, "Display the hover text for armor stands");
			ShowItemDescription = Config.Define<bool>(true, "Items", "Show Item Description", true, "Display the item description when hovering over items on the ground or on stands");
			ShowShieldGenMeter = Config.Define<bool>(true, "Shield Generator", "Show Shield Meter", true, "Display the power of the shield as a meter when looking at the generator");
		}
	}
	internal static class Extensions
	{
		internal static string CreateMeter(this Fireplace fireplace, float fuel)
		{
			return UI.CreateMeter(fuel, fireplace.m_maxFuel, 10);
		}

		internal static string CreateMeterOre(this Smelter smelter, float oreCount)
		{
			return UI.CreateMeter(oreCount, (float)smelter.m_maxOre, 10);
		}

		internal static string CreateMeterFuel(this Smelter smelter, float fuel)
		{
			return UI.CreateMeter(fuel, (float)smelter.m_maxFuel, 10);
		}

		internal static string CreateMeter(this ShieldGenerator shieldGen)
		{
			return UI.CreateMeter(shieldGen.GetFuel(), (float)shieldGen.m_maxFuel, 10);
		}

		internal static string GetHoverDescription(this ItemData itemData)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			if (!Configs.ShowItemDescription.Value)
			{
				return string.Empty;
			}
			string arg = StringExt.Localize(itemData.m_shared.m_description);
			return $"\n\n<color={UIColor.MinorInfo}>{arg}</color>";
		}
	}
	public class HoverItemUI : MonoBehaviour
	{
		private class Element
		{
			public readonly Image Icon;

			public readonly TMP_Text Label;

			private readonly GameObject _element;

			public bool IsVisible
			{
				get
				{
					return _element.activeSelf;
				}
				set
				{
					_element.SetActive(value);
				}
			}

			public Element(int index, Transform root)
			{
				//IL_00f6: 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_0125: Expected O, but got Unknown
				_element = Object.Instantiate<GameObject>(InventoryGui.instance.m_playerGrid.m_elementPrefab, root);
				((Object)_element).name = "Element_" + index;
				MonoBehaviour[] components = _element.GetComponents<MonoBehaviour>();
				for (int i = 0; i < components.Length; i++)
				{
					Object.Destroy((Object)(object)components[i]);
				}
				Label = ((Component)_element.transform.Find("amount")).GetComponent<TMP_Text>();
				Icon = ((Component)_element.transform.Find("icon")).GetComponent<Image>();
				UI.AddOutline(((Component)Icon).gameObject);
				Transform obj = _element.transform.Find("equiped");
				((Object)obj).name = "background";
				((Component)obj).gameObject.SetActive(false);
				Image component = ((Component)obj).GetComponent<Image>();
				((Graphic)component).color = new Color(0f, 0f, 0f, 0.3f);
				((Behaviour)component).enabled = true;
				foreach (Transform item in _element.transform)
				{
					Transform val = item;
					bool flag;
					switch (((Object)val).name)
					{
					case "icon":
					case "amount":
					case "background":
						flag = true;
						break;
					default:
						flag = false;
						break;
					}
					if (!flag)
					{
						Object.Destroy((Object)(object)((Component)val).gameObject);
					}
				}
			}
		}

		internal const int MaxIcons = 5;

		private const float DefaultScale = 0.8f;

		private const int IconSpacing = 4;

		private static readonly RectOffset PositionOffset = new RectOffset(76, 0, 0, 46);

		private GameObject _crosshairRootAnchor;

		private HorizontalLayoutGroup _layout;

		private readonly List<Element> _elements = new List<Element>();

		private bool _isDirty = true;

		internal static void Init()
		{
			((Component)Hud.instance).gameObject.AddComponent<HoverItemUI>().CreateStructure();
		}

		private void CreateStructure()
		{
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			//IL_0040: 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_005f: Unknown result type (might be due to invalid IL or missing references)
			_crosshairRootAnchor = new GameObject("ZenHoverItem");
			_crosshairRootAnchor.transform.SetParent(((Component)Hud.instance.m_crosshair).transform.parent, false);
			_crosshairRootAnchor.transform.localScale = Vector3.one * 0.8f;
			_crosshairRootAnchor.transform.localPosition = Vector3.zero;
			_layout = _crosshairRootAnchor.AddComponent<HorizontalLayoutGroup>();
			((HorizontalOrVerticalLayoutGroup)_layout).childControlWidth = false;
			((HorizontalOrVerticalLayoutGroup)_layout).childControlHeight = false;
			((HorizontalOrVerticalLayoutGroup)_layout).spacing = 4f;
			((LayoutGroup)_layout).padding = PositionOffset;
			((LayoutGroup)_layout).childAlignment = (TextAnchor)6;
			for (int i = 0; i < 5; i++)
			{
				_elements.Add(new Element(i, _crosshairRootAnchor.transform));
			}
		}

		internal static void Shutdown()
		{
			Hud instance = Hud.instance;
			Object.Destroy((Object)(object)((instance != null) ? ((Component)instance).GetComponent<HoverItemUI>() : null));
		}

		private void Update()
		{
			Clear();
		}

		private void OnDestroy()
		{
			Object.Destroy((Object)(object)_crosshairRootAnchor);
		}

		private void Clear()
		{
			if (!_isDirty)
			{
				return;
			}
			foreach (Element element in _elements)
			{
				element.IsVisible = false;
			}
			_isDirty = false;
		}

		public void UpdateHoverIcons(IEnumerable<Sprite?> icons)
		{
			UpdateHoverIcons(icons.Select((Sprite icon) => (icon, "")));
		}

		public void UpdateHoverIcons(IEnumerable<string?> prefabNames)
		{
			UpdateHoverIcons(prefabNames.Select((string prefabName) => (prefabName, "")));
		}

		public void UpdateHoverIcons(IEnumerable<(string? PrefabName, string Label)> elements)
		{
			UpdateHoverIcons(elements.Select<(string, string), (Sprite, string)>(((string PrefabName, string Label) e) => (Utility.IsNullOrWhiteSpace(e.PrefabName) ? null : ItemDataExt.GetIcon(ItemCache.Get(e.PrefabName)), e.Label)));
		}

		public void UpdateHoverIcons(IEnumerable<(Sprite? Icon, string Label)> elements)
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			foreach (var (tuple2, num) in IEnumerableExt.WithIndex<(Sprite, string)>(elements))
			{
				if (num < 5)
				{
					SetIcon(tuple2.Item1, num, tuple2.Item2);
					continue;
				}
				break;
			}
		}

		private void SetIcon(Sprite? icon, int index, string label, Vector2 offset = default(Vector2), bool flipX = false)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_002e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_003d: Unknown result type (might be due to invalid IL or missing references)
			if (Configs.ShowHoverIcons.Value)
			{
				if (flipX)
				{
					Vector3 localScale = _crosshairRootAnchor.transform.localScale;
					Transform transform = _crosshairRootAnchor.transform;
					Vector3 localScale2 = localScale;
					localScale2.x = 0f - localScale.x;
					transform.localScale = localScale2;
				}
				if (index < 5)
				{
					_elements[index].IsVisible = true;
					((Behaviour)_elements[index].Icon).enabled = Object.op_Implicit((Object)(object)icon);
					_elements[index].Icon.sprite = icon;
					((Behaviour)_elements[index].Label).enabled = label != "";
					_elements[index].Label.text = label;
				}
				_isDirty = true;
			}
		}
	}
	public static class ItemCache
	{
		private static readonly Dictionary<string, ItemDrop> PrefabCache = new Dictionary<string, ItemDrop>();

		public static ItemDrop Get(string prefabName)
		{
			//IL_004e: 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_0046: 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)
			prefabName = Utils.GetPrefabName(prefabName);
			if (PrefabCache.TryGetValue(prefabName, out ItemDrop value))
			{
				return value;
			}
			GameObject itemPrefab = ObjectDB.instance.GetItemPrefab(prefabName);
			ItemDrop obj = ((itemPrefab != null) ? itemPrefab.GetComponent<ItemDrop>() : null);
			if (obj == null)
			{
				string text = prefabName;
				Player localPlayer = Player.m_localPlayer;
				throw new MissingItemException(text, (Vector3)((localPlayer != null) ? ((Component)localPlayer).transform.position : default(Vector3)));
			}
			ItemDrop val = obj;
			return PrefabCache[prefabName] = val;
		}
	}
	[BepInPlugin("ZenDragon.ZenHoverItem", "ZenHoverItem", "0.2.15")]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[BepInDependency(/*Could not decode attribute arguments.*/)]
	[SynchronizationMode(/*Could not decode attribute arguments.*/)]
	[NetworkCompatibility(/*Could not decode attribute arguments.*/)]
	internal class Plugin : ZenMod<Plugin>
	{
		public const string PluginName = "ZenHoverItem";

		public const string PluginVersion = "0.2.15";

		public const string PluginGUID = "ZenDragon.ZenHoverItem";

		protected override void Setup()
		{
		}

		protected override void TitleScene(bool isFirstBoot)
		{
		}

		protected override void WorldStart()
		{
			HoverItemUI.Init();
		}

		protected override void Shutdown()
		{
			HoverItemUI.Shutdown();
		}
	}
}
namespace ZenHoverItem.HoverText
{
	[HarmonyPatch]
	public static class ArmorStand_HoverText
	{
		private static readonly List<string> ItemPrefabNames = new List<string>();

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Switch), "GetHoverText")]
		[HarmonyPriority(300)]
		private static void GetHoverText(Switch __instance, ref string __result)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			ArmorStand componentInParent = ((Component)__instance).GetComponentInParent<ArmorStand>();
			if (!Object.op_Implicit((Object)(object)componentInParent) || !componentInParent.m_nview.IsValid())
			{
				return;
			}
			ItemPrefabNames.Clear();
			foreach (var item3 in IEnumerableExt.WithIndex<ArmorStandSlot>((IEnumerable<ArmorStandSlot>)componentInParent.m_slots))
			{
				ArmorStandSlot item = item3.Item1;
				int item2 = item3.Item2;
				string @string = componentInParent.m_nview.GetZDO().GetString(item2 + "_item", "");
				string currentItemName = item.m_currentItemName;
				if (!Utility.IsNullOrWhiteSpace(@string) && !Utility.IsNullOrWhiteSpace(currentItemName))
				{
					if (Configs.ArmorStandShowHoverIcons.Value)
					{
						ItemPrefabNames.Add(@string);
					}
					if (Configs.ArmorStandShowHoverText.Value)
					{
						string arg = Localization.instance.Localize(currentItemName);
						__result += $"\n-  <color={UIColor.MinorInfo}>{arg}</color>";
					}
				}
			}
			if (Configs.ArmorStandShowHoverIcons.Value)
			{
				ItemPrefabNames.Sort((string a, string b) => Rank(b) - Rank(a));
				HudExt.UpdateHoverIcons(Hud.instance, ItemPrefabNames.ToArray());
			}
		}

		private static int Rank(string itemName)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0020: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Expected I4, but got Unknown
			ItemType itemType = ObjectDB.instance.GetItemPrefab(itemName).GetComponent<ItemDrop>().m_itemData.m_shared.m_itemType;
			switch (itemType - 3)
			{
			case 0:
			case 1:
			case 11:
			case 16:
			case 17:
			case 19:
				return 30;
			case 2:
				return 20;
			case 3:
				return 15;
			case 4:
			case 8:
			case 14:
				return 10;
			case 15:
				return 0;
			default:
				return -1;
			}
		}
	}
	[HarmonyPatch(typeof(Beehive))]
	public static class Beehive_HoverText
	{
		[HarmonyPostfix]
		[HarmonyPatch("GetHoverText")]
		private static void GetHoverText(Beehive __instance, ref string __result)
		{
			HudExt.UpdateHoverIcons(Hud.instance, new(Sprite, string)[1] { (ItemDataExt.GetIcon(__instance.m_honeyItem), $"{__instance.GetHoneyLevel()}/{__instance.m_maxHoney}") });
			__result = StringExt.Localize(__instance.m_name + "\n" + UI.PromptInteract + " $piece_beehive_extract");
			if (!__instance.CheckBiome())
			{
				__result += FormatMsg(__instance.m_areaText);
			}
			else if (!__instance.HaveFreeSpace())
			{
				__result += FormatMsg(__instance.m_freespaceText);
			}
			else if (!EnvMan.IsDaylight() && __instance.m_effectOnlyInDaylight)
			{
				__result += FormatMsg(__instance.m_sleepText);
			}
			else
			{
				__result += FormatMsg(__instance.m_happyText);
			}
			static string FormatMsg(string msg)
			{
				//IL_0005: Unknown result type (might be due to invalid IL or missing references)
				return StringExt.Localize($"\n\n<color={UIColor.MinorInfo}>{msg}</color>");
			}
		}
	}
	[HarmonyPatch(typeof(Container))]
	public static class Container_HoverText
	{
		[HarmonyPostfix]
		[HarmonyPatch("GetHoverText")]
		[HarmonyPriority(300)]
		private static void GetHoverText(Container __instance, ref string __result)
		{
			//IL_00c2: 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_0280: Unknown result type (might be due to invalid IL or missing references)
			//IL_0247: Unknown result type (might be due to invalid IL or missing references)
			//IL_021f: Unknown result type (might be due to invalid IL or missing references)
			if (!__instance.CheckAccess(Player.m_localPlayer.GetPlayerID()))
			{
				int startIndex = __result.IndexOf("\n", StringComparison.Ordinal);
				__result = __result.Remove(startIndex);
				__result += Localization.instance.Localize("\n$piece_noaccess");
				return;
			}
			bool flag = Object.op_Implicit((Object)(object)__instance.m_wagon);
			bool flag2 = !flag && Object.op_Implicit((Object)(object)((Component)__instance).GetComponentInParent<Ship>());
			if ((!WardAccessExt.CanAccessWard((MonoBehaviour)(object)__instance, false) && !flag && !flag2) || !((Object.op_Implicit((Object)(object)__instance.m_piece) && __instance.m_piece.IsPlacedByPlayer()) || flag || flag2))
			{
				return;
			}
			if (__instance.GetInventory().NrOfItems() == 0)
			{
				__result = __result.Replace(StringExt.Localize("( $piece_container_empty )"), "");
				__result += $"\n<color={UIColor.MinorInfo}>$piece_smelter_empty</color>";
				__result = StringExt.Localize(__result);
				return;
			}
			(string, int)[] array = ((Tally<string>)(object)InventoryExt.SumItemsByPrefabName(__instance.GetInventory())).Sorted().ToArray();
			HudExt.UpdateHoverIcons(Hud.instance, array.Select(((string Key, int Amount) sum) => (sum.Key, StringExt.ToHumanString(sum.Amount))).Take(Configs.ContainerMaxIcons.Value).ToArray());
			bool flag3 = !__instance.GetInventory().HaveEmptySlot();
			bool flag4 = flag3 && __instance.GetInventory().GetAllItems().All((ItemData item) => item.m_stack >= item.m_shared.m_maxStackSize);
			string text = (flag4 ? "$msg_itsfull" : null);
			if (array.Length == 1)
			{
				__result += $"\n<color={UIColor.MinorInfo}>{ItemDataExt.GetName(ItemCache.Get(array[0].Item1))}</color>";
			}
			else if (array.Length > 1)
			{
				int num = (Configs.ShowHoverIcons.Value ? Configs.ContainerMaxIcons.Value : 0);
				if (num > 0 && array.Length > num)
				{
					int num2 = array.Length - num;
					string arg = ((num2 == 1) ? "" : "s");
					__result += $"\n<color={UIColor.MinorInfo}>+{num2} More item{arg}...</color>";
				}
				else
				{
					__result += $"\n<color={UIColor.MinorInfo}>{array.Length} Items</color>";
				}
				if (!flag4 && flag3)
				{
					text = "No slots available";
				}
			}
			if (text != null)
			{
				__result += $"<color={UIColor.MinorInfo}> / {text}</color>";
			}
			__result = StringExt.Localize(__result);
		}
	}
	[HarmonyPatch(typeof(CookingStation))]
	public class CookingStation_HoverText
	{
		[HarmonyPostfix]
		[HarmonyPatch("GetHoverText")]
		internal static void GetHoverText(CookingStation __instance, ref string __result)
		{
			if (Utility.IsNullOrWhiteSpace(__result))
			{
				return;
			}
			List<string> list = new List<string>();
			string text = default(string);
			float num = default(float);
			Status val = default(Status);
			for (int i = 0; i < __instance.m_slots.Length; i++)
			{
				__instance.GetSlot(i, ref text, ref num, ref val);
				if (!Utility.IsNullOrWhiteSpace(text))
				{
					list.Add(text);
				}
			}
			HudExt.UpdateHoverIcons(Hud.instance, list.ToArray());
		}
	}
	[HarmonyPatch(typeof(Fermenter))]
	public static class Fermenter_HoverText
	{
		[HarmonyPrefix]
		[HarmonyPatch("GetHoverText")]
		private static void GetHoverText(Fermenter __instance, ref bool __runOriginal, ref string __result)
		{
			//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_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected I4, but got Unknown
			//IL_00cf: 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)
			__runOriginal = false;
			if (!WardAccessExt.CanAccessWard((MonoBehaviour)(object)__instance, false))
			{
				__result = Localization.instance.Localize(__instance.m_name + "\n$piece_noaccess");
				return;
			}
			__result = __instance.m_name;
			Status status = __instance.GetStatus();
			switch ((int)status)
			{
			case 0:
				__result += " ( $piece_container_empty )";
				__result = __result + "\n" + UI.PromptInteract + " $piece_fermenter_add";
				break;
			case 1:
				__result += " ( $piece_fermenter_fermenting )";
				break;
			case 3:
				__result += " ( $piece_fermenter_ready )";
				__result = __result + "\n" + UI.PromptInteract + " $piece_fermenter_tap";
				break;
			default:
				__result = __instance.m_name;
				break;
			}
			string contentName = __instance.GetContentName();
			if (!Utility.IsNullOrWhiteSpace(contentName))
			{
				__result += $"\n<color={UIColor.MinorInfo}>{contentName}</color>";
				string content = __instance.GetContent();
				Sprite icon = __instance.GetItemConversion(content).m_from.m_itemData.GetIcon();
				HudExt.UpdateHoverIcons(Hud.instance, (Sprite[])(object)new Sprite[1] { icon });
			}
			if (__instance.m_exposed)
			{
				__result += $"\n<color={UIColor.MajorInfo}>$piece_fermenter_exposed</color>";
			}
			__result = Localization.instance.Localize(__result);
		}
	}
	[HarmonyPatch(typeof(Fireplace))]
	public static class Fireplace_HoverText
	{
		private static readonly Dictionary<string, float> SecPerFuelDefaults = new Dictionary<string, float>();

		private static Fireplace? _useFireplace;

		[HarmonyPrefix]
		[HarmonyPatch("Interact")]
		private static void Interact_Prefix(Fireplace __instance)
		{
			_useFireplace = __instance;
		}

		[HarmonyPostfix]
		[HarmonyPatch("Interact")]
		private static void Interact_Postfix()
		{
			_useFireplace = null;
		}

		[HarmonyPrefix]
		[HarmonyPatch("UseItem")]
		private static void UseItem_Prefix(Fireplace __instance)
		{
			_useFireplace = __instance;
		}

		[HarmonyPostfix]
		[HarmonyPatch("UseItem")]
		private static void UseItem_Postfix()
		{
			_useFireplace = null;
		}

		[HarmonyPrefix]
		[HarmonyPatch("UpdateFireplace")]
		private static void UpdateFireplace(Fireplace __instance)
		{
			if (!SecPerFuelDefaults.TryGetValue(__instance.m_nview.GetPrefabName(), out var value))
			{
				string prefabName = __instance.m_nview.GetPrefabName();
				value = ZNetScene.instance.GetPrefab(prefabName).GetComponent<Fireplace>().m_secPerFuel;
				SecPerFuelDefaults.Add(prefabName, value);
			}
			__instance.m_secPerFuel = value * (Configs.AdjustFuelBurnRate.Value ? ((float)EnvMan.instance.m_dayLengthSec / 2000f) : 1f);
		}

		[HarmonyTranspiler]
		[HarmonyPatch("Interact")]
		private static IEnumerable<CodeInstruction> Interact_Transpile(IEnumerable<CodeInstruction> codes)
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(Mathf), "CeilToInt", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(Fireplace_HoverText), "CalcFuelLimit", (Type[])null, (Type[])null);
			return Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)methodInfo2);
		}

		[HarmonyTranspiler]
		[HarmonyPatch("UseItem")]
		private static IEnumerable<CodeInstruction> UseItem_Transpile(IEnumerable<CodeInstruction> codes)
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(Mathf), "CeilToInt", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(Fireplace_HoverText), "CalcFuelLimit", (Type[])null, (Type[])null);
			return Transpilers.MethodReplacer(codes, (MethodBase)methodInfo, (MethodBase)methodInfo2);
		}

		[HarmonyTranspiler]
		[HarmonyPatch("RPC_AddFuel")]
		private static IEnumerable<CodeInstruction> RPC_AddFuel_Transpile(IEnumerable<CodeInstruction> codes)
		{
			MethodInfo ceilToInt = AccessTools.Method(typeof(Mathf), "CeilToInt", (Type[])null, (Type[])null);
			return Transpilers.Manipulator(codes, (Func<CodeInstruction, bool>)((CodeInstruction ci) => CodeInstructionExtensions.Calls(ci, ceilToInt)), (Action<CodeInstruction>)delegate(CodeInstruction ci)
			{
				ci.opcode = OpCodes.Nop;
				ci.operand = null;
			});
		}

		private static float CalcFuelLimit(float fuel)
		{
			if ((Object)(object)_useFireplace == (Object)null)
			{
				Log.Warning((object)"_useFireplace is missing, can not check remaining fueldays.  Returning CeilToInt instead.Did a mod break Fireplace.UseItem or Fireplace.Interact on Prefix/Postfix?", (ushort)0);
				return Mathf.CeilToInt(fuel);
			}
			if (FireplaceExt.IsFuelDaysEmpty(_useFireplace, (float?)null) || FireplaceExt.IsFuelDaysFull(_useFireplace, (float?)null))
			{
				return Mathf.Ceil(fuel);
			}
			return fuel;
		}

		[HarmonyPrefix]
		[HarmonyPatch("GetHoverText")]
		private static void GetHoverText(Fireplace __instance, ref bool __runOriginal, ref string __result)
		{
			//IL_0147: Unknown result type (might be due to invalid IL or missing references)
			if (!__instance.m_infiniteFuel && __instance.m_nview.IsValid())
			{
				__runOriginal = false;
				ItemData itemData = __instance.m_fuelItem.m_itemData;
				float num = default(float);
				string arg = UI.RemainingTimeText(FireplaceExt.FuelTimeRemaining(__instance, ref num), __instance.m_secPerFuel);
				bool flag = __instance.m_fireworkItemList.Length != 0 && ((Humanoid)Player.m_localPlayer).GetInventory().GetAllItems().Any((ItemData item) => ItemDataExt.GetName(item).StartsWith("$item_fireworkrocket"));
				string text = string.Empty;
				if (__instance.m_canRefill)
				{
					text = "\n" + UI.PromptInteract + " $piece_use " + ItemDataExt.GetName(itemData) + (flag ? ("\n" + UI.PromptUseItem + " $piece_useitem") : string.Empty);
				}
				else if (__instance.m_canTurnOff && num > 0f)
				{
					text = "\n" + UI.PromptInteract + " $piece_use";
				}
				string text2 = (Configs.ShowFuelMeter.Value.HasFlag(Configs.FuelMeterType.Fireplace) ? __instance.CreateMeter(num) : string.Empty);
				string text3 = (Configs.ShowFuelDays.Value ? $"\n<color={UIColor.MinorInfo}>Fuel remaining: {arg}</color>" : string.Empty);
				string text4 = __instance.m_name + text + text3 + text2;
				__result = Localization.instance.Localize(text4);
				if (Configs.ShowHoverIconForFuel.Value.HasFlag(Configs.FuelMeterType.Fireplace) && num > 0f)
				{
					string item2 = (__instance.m_infiniteFuel ? string.Empty : $"{Mathf.CeilToInt(num)}/{__instance.m_maxFuel}");
					HudExt.UpdateHoverIcons(Hud.instance, new(Sprite, string)[1] { (itemData.GetIcon(), item2) });
				}
			}
		}
	}
	[HarmonyPatch(typeof(ItemDrop))]
	public static class ItemDrop_HoverText
	{
		[HarmonyPostfix]
		[HarmonyPatch("GetHoverText")]
		[HarmonyPriority(200)]
		private static void GetHoverText(ItemDrop __instance, ref string __result)
		{
			__result = Regex.Replace(__result, "\\sx\\d+$", string.Empty, RegexOptions.Multiline);
			__result += __instance.m_itemData.GetHoverDescription();
			int stack = __instance.m_itemData.m_stack;
			if (stack > 1)
			{
				HudExt.UpdateHoverIcons(Hud.instance, new(Sprite, string)[1] { (ItemDataExt.GetIcon(__instance), StringExt.ToHumanString(stack)) });
			}
			else
			{
				HudExt.UpdateHoverIcons(Hud.instance, (Sprite[])(object)new Sprite[1] { ItemDataExt.GetIcon(__instance) });
			}
		}
	}
	[HarmonyPatch(typeof(ItemStand))]
	public static class ItemStand_HoverText
	{
		private static bool IsValid(ItemStand itemStand)
		{
			if (!itemStand.HaveAttachment() || !ItemStandExt.CanBeRemoved(itemStand) || ItemStandExt.IsBossStone(itemStand))
			{
				return false;
			}
			if (Utility.IsNullOrWhiteSpace(itemStand.m_visualName))
			{
				return false;
			}
			return true;
		}

		[HarmonyPostfix]
		[HarmonyPatch("GetHoverText")]
		[HarmonyPriority(300)]
		private static void GetHoverText(ItemStand __instance, ref string __result)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if (IsValid(__instance))
			{
				Sprite icon = ItemDataExt.GetIcon(ItemCache.Get(__instance.m_visualName), __instance.m_visualVariant);
				HudExt.UpdateHoverIcons(Hud.instance, (Sprite[])(object)new Sprite[1] { icon });
				int startIndex = __result.IndexOf("\n", StringComparison.Ordinal);
				__result = __instance.GetHoverName() + __result.Substring(startIndex);
				__result += $"\n<color={UIColor.MinorInfo}>{__instance.m_currentItemName}</color>";
				__result = Localization.instance.Localize(__result);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("GetHoverText")]
		[HarmonyPriority(200)]
		private static void GetHoverText_ItemDescription(ItemStand __instance, ref string __result)
		{
			if (IsValid(__instance))
			{
				ItemDrop val = ItemCache.Get(__instance.m_visualName);
				__result += val.m_itemData.GetHoverDescription();
			}
		}
	}
	[HarmonyPatch]
	public static class Oven_HoverText
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(Switch), "GetHoverText")]
		[HarmonyPriority(0)]
		internal static void GetHoverText(Switch __instance, ref string __result)
		{
			CookingStation componentInParent = ((Component)__instance).GetComponentInParent<CookingStation>();
			if (Object.op_Implicit((Object)(object)componentInParent))
			{
				CookingStation_HoverText.GetHoverText(componentInParent, ref __result);
			}
		}
	}
	[HarmonyPatch(typeof(Pickable))]
	public static class Pickable_HoverText
	{
		[HarmonyPostfix]
		[HarmonyPatch("GetHoverText")]
		[HarmonyPriority(200)]
		private static void GetHoverText(Pickable __instance, ref string __result)
		{
			if (!__instance.m_picked)
			{
				ItemDrop val = ItemCache.Get(((Object)__instance.m_itemPrefab).name);
				__result += val.m_itemData.GetHoverDescription();
				HudExt.UpdateHoverIcons(Hud.instance, (Sprite[])(object)new Sprite[1] { ItemDataExt.GetIcon(val) });
			}
		}
	}
	[HarmonyPatch(typeof(PickableItem))]
	public static class PickableItem_HoverText
	{
		[HarmonyPostfix]
		[HarmonyPatch("GetHoverText")]
		[HarmonyPriority(200)]
		private static void GetHoverText(PickableItem __instance, ref string __result)
		{
			if (!__instance.m_picked && Object.op_Implicit((Object)(object)__instance.m_itemPrefab))
			{
				__result += __instance.m_itemPrefab.m_itemData.GetHoverDescription();
				HudExt.UpdateHoverIcons(Hud.instance, (Sprite[])(object)new Sprite[1] { ItemDataExt.GetIcon(__instance.m_itemPrefab) });
			}
		}
	}
	[HarmonyPatch(typeof(SapCollector))]
	public class SapCollector_HoverText
	{
		[HarmonyPrefix]
		[HarmonyPatch("GetHoverText")]
		private static void GetHoverText(SapCollector __instance, ref bool __runOriginal, ref string __result)
		{
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			ItemData itemData = __instance.m_spawnItem.m_itemData;
			int level = __instance.GetLevel();
			HudExt.UpdateHoverIcons(Hud.instance, new(Sprite, string)[1] { (itemData.GetIcon(), $"{level}/{__instance.m_maxLevel}") });
			__runOriginal = false;
			string text = __instance.m_name + "\n" + UI.PromptInteract + " " + __instance.m_extractText + $"\n<color={UIColor.MinorInfo}>{__instance.GetStatusText()}</color>";
			__result = Localization.instance.Localize(text);
		}
	}
	[HarmonyPatch]
	internal static class ShieldGen
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(Switch), "GetHoverText")]
		[HarmonyPriority(100)]
		private static void Switch_ShieldGenerator_GetHoverText(Switch __instance, ref string __result)
		{
			ShieldGenerator componentInParent = ((Component)__instance).GetComponentInParent<ShieldGenerator>();
			if (Object.op_Implicit((Object)(object)componentInParent) && Configs.ShowShieldGenMeter.Value)
			{
				__result = Regex.Replace(__result, " \\(.+?\\)$", string.Empty, RegexOptions.Multiline);
				__result += componentInParent.CreateMeter();
			}
		}
	}
	[HarmonyPatch(typeof(Smelter))]
	internal static class Smelter_HoverText
	{
		[HarmonyPostfix]
		[HarmonyPatch("OnHoverEmptyOre")]
		private static void GetHoverText_EmptyOre(Smelter __instance, ref string __result)
		{
			ItemConversion itemConversion = __instance.GetItemConversion(__instance.GetQueuedOre());
			if (itemConversion != null)
			{
				ItemData itemData = itemConversion.m_to.m_itemData;
				HudExt.UpdateHoverIcons(Hud.instance, new(Sprite, string)[1] { (itemData.GetIcon(), __instance.GetProcessedQueueSize().ToString()) });
				__result = Regex.Replace(__result, "\\(.+?\\)", string.Empty, RegexOptions.Multiline);
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("OnHoverAddFuel")]
		private static void GetHoverText_AddFuel(Smelter __instance, ref string __result)
		{
			int num = Mathf.CeilToInt(__instance.GetFuel());
			ItemData itemData = __instance.m_fuelItem.m_itemData;
			string text = "\n" + UI.PromptInteract + " $piece_smelter_add " + ItemDataExt.GetName(itemData);
			string text2 = (Configs.ShowFuelMeter.Value.HasFlag(Configs.FuelMeterType.SmelterFuel) ? __instance.CreateMeterFuel(num) : string.Empty);
			string text3 = (Configs.ShowHoverIconForFuel.Value.HasFlag(Configs.FuelMeterType.SmelterFuel) ? string.Empty : $" ({num}/{__instance.m_maxFuel})");
			string text4 = __instance.m_name + text3 + text + text2;
			__result = Localization.instance.Localize(text4);
			if (Configs.ShowHoverIconForFuel.Value.HasFlag(Configs.FuelMeterType.SmelterFuel) && num > 0)
			{
				HudExt.UpdateHoverIcons(Hud.instance, new(Sprite, string)[1] { (itemData.GetIcon(), $"{num}/{__instance.m_maxFuel}") });
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("OnHoverAddOre")]
		[HarmonyPriority(100)]
		private static void GetHoverText_AddOre(Smelter __instance, ref string __result)
		{
			//IL_0156: 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)
			List<string> rawQueue = new List<string>();
			int queueSize = __instance.GetQueueSize();
			for (int i = 0; i < queueSize; i++)
			{
				string @string = __instance.m_nview.GetZDO().GetString("item" + i, "");
				rawQueue.Add(@string);
			}
			List<(string, string)> list = (from ore in rawQueue.Select((string name, int index) => (name, index))
				group ore by (ore.PrefabName, rawQueue.Take(ore.Index).Count((string name) => name != ore.PrefabName)) into @group
				select (@group.Key.PrefabName, StringExt.ToHumanString(@group.Count()))).ToList();
			if (Configs.ShowHoverIconForFuel.Value.HasFlag(Configs.FuelMeterType.SmelterOre))
			{
				HudExt.UpdateHoverIcons(Hud.instance, list.ToArray());
			}
			string text = string.Empty;
			if (Configs.ShowFuelMeter.Value.HasFlag(Configs.FuelMeterType.SmelterOre))
			{
				__result = Regex.Replace(__result, "\\(.+?\\)", string.Empty, RegexOptions.Multiline);
				text += __instance.CreateMeterOre(queueSize);
			}
			foreach (var item in list)
			{
				ItemDrop val = ItemCache.Get(item.Item1);
				text += $"\n-   <color={UIColor.MinorInfo}>{ItemDataExt.GetName(val)}</color>";
			}
			if (__instance.m_requiresRoof && !__instance.m_haveRoof)
			{
				text += $"\n<color={UIColor.MajorInfo}>$piece_smelter_reqroof</color>";
				__result = __result.Replace(StringExt.Localize(" <color=yellow>$piece_smelter_reqroof</color>"), string.Empty);
			}
			__result += Localization.instance.Localize(text);
		}
	}
	[HarmonyPatch]
	internal static class TombStone_HoverText
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(TombStone), "GetHoverText")]
		private static void TombStone_GetHoverText(TombStone __instance, ref string __result)
		{
			HudExt.UpdateHoverIcons(Hud.instance, (Sprite[])(object)new Sprite[1] { Minimap.instance.GetSprite((PinType)4) });
		}
	}
	[HarmonyPatch(typeof(WispSpawner))]
	public static class WispSpawner_HoverText
	{
		[HarmonyPostfix]
		[HarmonyPatch("GetHoverText")]
		private static void GetHoverText(WispSpawner __instance, ref string __result)
		{
			int startIndex = __result.IndexOf("(", StringComparison.Ordinal);
			__result = __result.Insert(startIndex, "\n");
		}
	}
}