Decompiled source of Peak Item Tooltip v0.1.0

BepInEx/plugins/peak-item-tooltip.dll

Decompiled 2 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Peak;
using TMPro;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.UI.ProceduralImage;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.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 PeakItemTooltip
{
	public class ItemInfo
	{
		[JsonProperty("type")]
		[JsonConverter(typeof(StringOrStringArrayConverter))]
		public List<string> Types = new List<string>();

		[JsonProperty("description")]
		public string Description = "";
	}
	public class StringOrStringArrayConverter : JsonConverter
	{
		public override bool CanConvert(Type objectType)
		{
			return objectType == typeof(List<string>);
		}

		public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: Invalid comparison between Unknown and I4
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Invalid comparison between Unknown and I4
			List<string> list = new List<string>();
			if ((int)reader.TokenType == 11)
			{
				return list;
			}
			if ((int)reader.TokenType == 2)
			{
				foreach (JToken item in JArray.Load(reader))
				{
					string text = ((object)item)?.ToString();
					if (!string.IsNullOrEmpty(text))
					{
						list.Add(text);
					}
				}
			}
			else
			{
				string text2 = reader.Value?.ToString();
				if (!string.IsNullOrEmpty(text2))
				{
					list.Add(text2);
				}
			}
			return list;
		}

		public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
		{
			List<string> list = value as List<string>;
			if (list != null && list.Count == 1)
			{
				writer.WriteValue(list[0]);
				return;
			}
			writer.WriteStartArray();
			if (list != null)
			{
				foreach (string item in list)
				{
					writer.WriteValue(item);
				}
			}
			writer.WriteEndArray();
		}
	}
	public class DescriptionFile
	{
		[JsonProperty("types")]
		public Dictionary<string, string> Types = new Dictionary<string, string>();

		[JsonProperty("items")]
		public Dictionary<string, ItemInfo> Items = new Dictionary<string, ItemInfo>();
	}
	public class Descriptions
	{
		public const string FileName = "peak-item-tooltip.descriptions.json";

		private readonly string _path;

		private Dictionary<string, ItemInfo> _items = new Dictionary<string, ItemInfo>(StringComparer.OrdinalIgnoreCase);

		private Dictionary<string, string> _types = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);

		private Dictionary<string, Color> _typeColours = new Dictionary<string, Color>(StringComparer.OrdinalIgnoreCase);

		private DateTime _lastWriteUtc;

		private const string DefaultFileContents = "{\n          \"types\": {\n        },\n          \"items\": {\n            \"EXAMPLE_KEY\": {\n              \"type\": \"\",\n              \"description\": \"\"\n                }\n            }\n        }\n        ";

		public string Path_ => _path;

		public Descriptions()
		{
			_path = Path.Combine(Paths.ConfigPath, "peak-item-tooltip.descriptions.json");
		}

		public void Initialize()
		{
			try
			{
				if (!File.Exists(_path))
				{
					string contents = LoadEmbeddedDefault() ?? "{\n          \"types\": {\n        },\n          \"items\": {\n            \"EXAMPLE_KEY\": {\n              \"type\": \"\",\n              \"description\": \"\"\n                }\n            }\n        }\n        ";
					File.WriteAllText(_path, contents);
					Plugin.Log.LogInfo((object)("Created description file at " + _path));
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not create description file: " + ex.Message));
			}
			Load();
		}

		public void MaybeReload()
		{
			try
			{
				if (File.Exists(_path) && File.GetLastWriteTimeUtc(_path) != _lastWriteUtc)
				{
					Load();
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Description reload check failed: " + ex.Message));
			}
		}

		public bool TryGet(string key, out ItemInfo info)
		{
			if (!string.IsNullOrEmpty(key))
			{
				return _items.TryGetValue(key, out info);
			}
			info = null;
			return false;
		}

		public bool TryGetTypeColour(string typeName, out Color colour)
		{
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (!string.IsNullOrEmpty(typeName))
			{
				return _typeColours.TryGetValue(typeName, out colour);
			}
			colour = default(Color);
			return false;
		}

		private void Load()
		{
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				DescriptionFile descriptionFile = JsonConvert.DeserializeObject<DescriptionFile>(File.ReadAllText(_path)) ?? new DescriptionFile();
				Dictionary<string, ItemInfo> dictionary = new Dictionary<string, ItemInfo>(StringComparer.OrdinalIgnoreCase);
				if (descriptionFile.Items != null)
				{
					foreach (KeyValuePair<string, ItemInfo> item in descriptionFile.Items)
					{
						if (item.Value != null)
						{
							dictionary[item.Key] = item.Value;
						}
					}
				}
				Dictionary<string, string> dictionary2 = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
				Dictionary<string, Color> dictionary3 = new Dictionary<string, Color>(StringComparer.OrdinalIgnoreCase);
				if (descriptionFile.Types != null)
				{
					Color value = default(Color);
					foreach (KeyValuePair<string, string> type in descriptionFile.Types)
					{
						if (!string.IsNullOrEmpty(type.Key) && type.Value != null)
						{
							dictionary2[type.Key] = type.Value;
							if (ColorUtility.TryParseHtmlString(type.Value, ref value))
							{
								dictionary3[type.Key] = value;
							}
						}
					}
				}
				_items = dictionary;
				_types = dictionary2;
				_typeColours = dictionary3;
				_lastWriteUtc = File.GetLastWriteTimeUtc(_path);
				Plugin.Log.LogInfo((object)string.Format("Loaded {0} item description(s) and {1} type(s) from {2}", _items.Count, _types.Count, "peak-item-tooltip.descriptions.json"));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Failed to parse peak-item-tooltip.descriptions.json: " + ex.Message + " (keeping previous data)"));
			}
		}

		private static string LoadEmbeddedDefault()
		{
			try
			{
				Assembly assembly = typeof(Descriptions).Assembly;
				string text = assembly.GetManifestResourceNames().FirstOrDefault((string n) => n.EndsWith("default-descriptions.json", StringComparison.OrdinalIgnoreCase));
				if (text == null)
				{
					return null;
				}
				using Stream stream = assembly.GetManifestResourceStream(text);
				using StreamReader streamReader = new StreamReader(stream);
				return streamReader.ReadToEnd();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Could not read embedded default descriptions: " + ex.Message));
				return null;
			}
		}
	}
	public static class ItemModifiers
	{
		private static readonly Dictionary<STATUSTYPE, Color> Colours = new Dictionary<STATUSTYPE, Color>
		{
			{
				(STATUSTYPE)0,
				Hex("#E4463B")
			},
			{
				(STATUSTYPE)1,
				Hex("#F2C43D")
			},
			{
				(STATUSTYPE)2,
				Hex("#4FA3FF")
			},
			{
				(STATUSTYPE)3,
				Hex("#A65AD8")
			},
			{
				(STATUSTYPE)4,
				Hex("#FF7043")
			},
			{
				(STATUSTYPE)5,
				Hex("#B5179E")
			},
			{
				(STATUSTYPE)6,
				Hex("#5AD1C4")
			},
			{
				(STATUSTYPE)7,
				Hex("#B0A08A")
			},
			{
				(STATUSTYPE)8,
				Hex("#FF8C1A")
			},
			{
				(STATUSTYPE)9,
				Hex("#6FBF4B")
			},
			{
				(STATUSTYPE)10,
				Hex("#9CCC65")
			},
			{
				(STATUSTYPE)11,
				Hex("#D0D0D0")
			},
			{
				(STATUSTYPE)12,
				Hex("#C9A66B")
			},
			{
				(STATUSTYPE)13,
				Hex("#9E9E9E")
			},
			{
				(STATUSTYPE)14,
				Hex("#4CAF50")
			}
		};

		private static readonly Color StaminaColour = Hex("#7CD64B");

		private static readonly Color Fallback = Color.white;

		public static string Format(Item item)
		{
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: 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_00c8: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)item == (Object)null)
			{
				return "";
			}
			StringBuilder stringBuilder = new StringBuilder();
			bool first = true;
			Action_RestoreHunger[] componentsInChildren = ((Component)item).GetComponentsInChildren<Action_RestoreHunger>(true);
			foreach (Action_RestoreHunger val in componentsInChildren)
			{
				if (!((Object)(object)val == (Object)null))
				{
					AppendLine(stringBuilder, ref first, ColourFor((STATUSTYPE)1), 0f - val.restorationAmount, "Hunger");
				}
			}
			Action_InflictPoison[] componentsInChildren2 = ((Component)item).GetComponentsInChildren<Action_InflictPoison>(true);
			foreach (Action_InflictPoison val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					AppendLine(stringBuilder, ref first, ColourFor((STATUSTYPE)3), val2.poisonPerSecond * val2.inflictionTime, "Poison");
				}
			}
			Action_ModifyStatus[] componentsInChildren3 = ((Component)item).GetComponentsInChildren<Action_ModifyStatus>(true);
			foreach (Action_ModifyStatus val3 in componentsInChildren3)
			{
				if (!((Object)(object)val3 == (Object)null))
				{
					AppendLine(stringBuilder, ref first, ColourFor(val3.statusType), val3.changeAmount, ((object)Unsafe.As<STATUSTYPE, STATUSTYPE>(ref val3.statusType)/*cast due to .constrained prefix*/).ToString());
				}
			}
			Action_GiveExtraStamina[] componentsInChildren4 = ((Component)item).GetComponentsInChildren<Action_GiveExtraStamina>(true);
			foreach (Action_GiveExtraStamina val4 in componentsInChildren4)
			{
				if (!((Object)(object)val4 == (Object)null))
				{
					AppendLine(stringBuilder, ref first, StaminaColour, val4.amount, "Extra Stamina");
				}
			}
			AppendPetrify(stringBuilder, ref first, item);
			return stringBuilder.ToString();
		}

		private static void AppendPetrify(StringBuilder sb, ref bool first, Item item)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_012f: 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)
			Color colour = ColourFor((STATUSTYPE)13);
			MonoBehaviour[] componentsInChildren = ((Component)item).GetComponentsInChildren<MonoBehaviour>(true);
			foreach (MonoBehaviour val in componentsInChildren)
			{
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				FieldInfo[] fields = ((object)val).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (!fieldInfo.Name.StartsWith("petrify", StringComparison.OrdinalIgnoreCase))
					{
						continue;
					}
					int signedPoints;
					if (fieldInfo.FieldType == typeof(int))
					{
						signedPoints = (int)fieldInfo.GetValue(val);
					}
					else
					{
						if (!(fieldInfo.FieldType == typeof(float)))
						{
							continue;
						}
						signedPoints = Mathf.RoundToInt((float)fieldInfo.GetValue(val) * 100f);
					}
					AppendPoints(sb, ref first, colour, signedPoints, PetrifyLabel(fieldInfo.Name));
				}
			}
			Action_HealingGem[] componentsInChildren2 = ((Component)item).GetComponentsInChildren<Action_HealingGem>(true);
			foreach (Action_HealingGem val2 in componentsInChildren2)
			{
				if (!((Object)(object)val2 == (Object)null))
				{
					int lowPoints = Mathf.RoundToInt(val2.minPetrify * 100f);
					int highPoints = Mathf.RoundToInt(val2.maxPetrify * 100f);
					AppendPointsRange(sb, ref first, colour, lowPoints, highPoints, "Petrify");
				}
			}
		}

		private static string PetrifyLabel(string fieldName)
		{
			string text = ((fieldName.Length > "petrify".Length) ? fieldName.Substring("petrify".Length) : "");
			if (string.IsNullOrEmpty(text))
			{
				return "Petrify";
			}
			StringBuilder stringBuilder = new StringBuilder();
			string text2 = text;
			foreach (char c in text2)
			{
				if (char.IsUpper(c) && stringBuilder.Length > 0)
				{
					stringBuilder.Append(' ');
				}
				stringBuilder.Append(char.ToLowerInvariant(c));
			}
			return "Petrify (" + stringBuilder?.ToString() + ")";
		}

		private static void AppendLine(StringBuilder sb, ref bool first, Color colour, float signedFraction, string label)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			AppendPoints(sb, ref first, colour, Mathf.RoundToInt(signedFraction * 100f), label);
		}

		private static void AppendPoints(StringBuilder sb, ref bool first, Color colour, int signedPoints, string label)
		{
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			if (signedPoints != 0)
			{
				string value = ((signedPoints > 0) ? "+" : "-");
				string value2 = ColorUtility.ToHtmlStringRGB(colour);
				if (!first)
				{
					sb.Append('\n');
				}
				first = false;
				sb.Append("<color=#").Append(value2).Append('>')
					.Append(value)
					.Append(Mathf.Abs(signedPoints))
					.Append(' ')
					.Append(label)
					.Append("</color>");
			}
		}

		private static void AppendPointsRange(StringBuilder sb, ref bool first, Color colour, int lowPoints, int highPoints, string label)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0017: Unknown result type (might be due to invalid IL or missing references)
			if (lowPoints == highPoints)
			{
				AppendPoints(sb, ref first, colour, highPoints, label);
			}
			else if (highPoints != 0)
			{
				string value = ColorUtility.ToHtmlStringRGB(colour);
				if (!first)
				{
					sb.Append('\n');
				}
				first = false;
				sb.Append("<color=#").Append(value).Append('>')
					.Append('+')
					.Append(lowPoints)
					.Append('–')
					.Append(highPoints)
					.Append(' ')
					.Append(label)
					.Append("</color>");
			}
		}

		private static Color ColourFor(STATUSTYPE type)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0015: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			if (!Colours.TryGetValue(type, out var value))
			{
				return Fallback;
			}
			return value;
		}

		private static Color Hex(string s)
		{
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			Color result = default(Color);
			ColorUtility.TryParseHtmlString(s, ref result);
			return result;
		}
	}
	public class PluginConfig
	{
		public readonly ConfigEntry<bool> Enabled;

		public readonly ConfigEntry<bool> HotReload;

		public readonly ConfigEntry<bool> ShowWhileHolding;

		public readonly ConfigEntry<float> OffsetX;

		public readonly ConfigEntry<float> OffsetY;

		public readonly ConfigEntry<float> Scale;

		public readonly ConfigEntry<float> Width;

		public readonly ConfigEntry<float> BackgroundOpacity;

		public readonly ConfigEntry<bool> ShowIcon;

		public readonly ConfigEntry<bool> ShowName;

		public readonly ConfigEntry<bool> ShowType;

		public readonly ConfigEntry<bool> ShowDescription;

		public readonly ConfigEntry<bool> ShowModifiers;

		public readonly ConfigEntry<float> IconSize;

		public readonly ConfigEntry<float> NameFontSize;

		public readonly ConfigEntry<float> TypeFontSize;

		public readonly ConfigEntry<float> DescriptionFontSize;

		public readonly ConfigEntry<float> ModifierFontSize;

		public PluginConfig(ConfigFile cfg)
		{
			//IL_00c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Expected O, but got Unknown
			Enabled = cfg.Bind<bool>("Widget", "Enabled", true, "Master toggle for the hover info widget.");
			HotReload = cfg.Bind<bool>("Advanced", "HotReload", true, "Watch the config and descriptions files for changes and apply them live without restarting the game. Handy while tuning; safe to disable if you never edit these files mid-session. Note: turning this back ON requires a game restart to take effect (while off, nothing is watching the file).");
			ShowWhileHolding = cfg.Bind<bool>("Widget", "ShowWhileHolding", true, "Also show the tooltip for the item you are holding. If off, it only appears when hovering.");
			OffsetX = cfg.Bind<float>("Widget", "OffsetX", -710f, "Horizontal offset from the screen center; positive = right (1920x1080 reference pixels).");
			OffsetY = cfg.Bind<float>("Widget", "OffsetY", -220f, "Vertical offset from the screen center; positive = up (1920x1080 reference pixels).");
			Scale = cfg.Bind<float>("Widget", "Scale", 1.15f, new ConfigDescription("Overall scale multiplier.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 5f), Array.Empty<object>()));
			Width = cfg.Bind<float>("Widget", "Width", 320f, "Widget width in reference pixels; the description wraps to this width.");
			BackgroundOpacity = cfg.Bind<float>("Widget", "BackgroundOpacity", 0.75f, new ConfigDescription("Background panel opacity.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			ShowIcon = cfg.Bind<bool>("Fields", "ShowIcon", true, "Show the item icon.");
			ShowName = cfg.Bind<bool>("Fields", "ShowName", true, "Show the item name.");
			ShowType = cfg.Bind<bool>("Fields", "ShowType", true, "Show the item type (e.g. Mystical, Consumable).");
			ShowDescription = cfg.Bind<bool>("Fields", "ShowDescription", true, "Show the description.");
			ShowModifiers = cfg.Bind<bool>("Fields", "ShowModifiers", true, "Show item stat modifiers (e.g. +10 Poison).");
			IconSize = cfg.Bind<float>("Fields", "IconSize", 48f, "Icon width/height in reference pixels.");
			NameFontSize = cfg.Bind<float>("Fields", "NameFontSize", 22f, "Name font size.");
			TypeFontSize = cfg.Bind<float>("Fields", "TypeFontSize", 15f, "Type font size.");
			DescriptionFontSize = cfg.Bind<float>("Fields", "DescriptionFontSize", 16f, "Description font size.");
			ModifierFontSize = cfg.Bind<float>("Fields", "ModifierFontSize", 16f, "Modifier font size.");
		}
	}
	[BepInPlugin("peak-item-tooltip", "peak-item-tooltip", "0.1.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string PluginGuid = "peak-item-tooltip";

		public const string PluginName = "peak-item-tooltip";

		public const string PluginVersion = "0.1.0";

		internal static ManualLogSource Log;

		private Descriptions _descriptions;

		private PluginConfig _config;

		private Widget _widget;

		private Item _lastItem;

		private float _nextContentRefresh;

		private const float ContentRefreshInterval = 0.25f;

		private bool _configDirty;

		private float _nextReloadCheck;

		private const float ReloadCheckInterval = 1f;

		private DateTime _configWriteUtc;

		private void Awake()
		{
			Log = ((BaseUnityPlugin)this).Logger;
			_descriptions = new Descriptions();
			_descriptions.Initialize();
			_config = new PluginConfig(((BaseUnityPlugin)this).Config);
			_widget = new Widget(_config);
			_configWriteUtc = SafeConfigWriteTime();
			Log.LogInfo((object)"peak-item-tooltip [0.1.0] loaded •ᴗ•");
		}

		private void Update()
		{
			if (_config.HotReload.Value && Time.unscaledTime >= _nextReloadCheck)
			{
				_nextReloadCheck = Time.unscaledTime + 1f;
				_descriptions.MaybeReload();
				MaybeReloadConfig();
			}
			Item val = ResolveTargetItem();
			if ((Object)(object)val == (Object)null)
			{
				_widget.Hide();
				_lastItem = null;
				_configDirty = false;
				return;
			}
			bool num = (Object)(object)val != (Object)(object)_lastItem;
			bool flag = Time.unscaledTime >= _nextContentRefresh;
			if (num || flag || _configDirty)
			{
				_lastItem = val;
				_nextContentRefresh = Time.unscaledTime + 0.25f;
				_configDirty = false;
				_widget.Show(val, _descriptions);
			}
		}

		private Item ResolveTargetItem()
		{
			Interaction instance = Interaction.instance;
			if ((Object)(object)instance == (Object)null)
			{
				return null;
			}
			if (_config.ShowWhileHolding.Value)
			{
				Character localCharacter = Character.localCharacter;
				Item val = (((Object)(object)localCharacter != (Object)null && (Object)(object)localCharacter.data != (Object)null) ? localCharacter.data.currentItem : null);
				if ((Object)(object)val != (Object)null)
				{
					return val;
				}
			}
			IInteractible currentHovered = instance.currentHovered;
			return (Item)(object)((currentHovered is Item) ? currentHovered : null);
		}

		private void MaybeReloadConfig()
		{
			try
			{
				DateTime dateTime = SafeConfigWriteTime();
				if (dateTime != _configWriteUtc)
				{
					_configWriteUtc = dateTime;
					((BaseUnityPlugin)this).Config.Reload();
					_configDirty = true;
				}
			}
			catch (Exception ex)
			{
				Log.LogWarning((object)("Config reload check failed: " + ex.Message));
			}
		}

		private DateTime SafeConfigWriteTime()
		{
			string configFilePath = ((BaseUnityPlugin)this).Config.ConfigFilePath;
			if (!File.Exists(configFilePath))
			{
				return default(DateTime);
			}
			return File.GetLastWriteTimeUtc(configFilePath);
		}
	}
	public class Widget
	{
		private readonly PluginConfig _cfg;

		private GameObject _canvasGo;

		private GameObject _rootGo;

		private RectTransform _root;

		private ProceduralImage _background;

		private ProceduralImage _border;

		private GameObject _iconGo;

		private RawImage _icon;

		private LayoutElement _iconLayout;

		private TextMeshProUGUI _name;

		private TextMeshProUGUI _type;

		private TextMeshProUGUI _description;

		private TextMeshProUGUI _modifiers;

		private static readonly Color TypeFallbackColour = new Color(0.7f, 0.7f, 0.7f, 1f);

		private const float CornerRadius = 12f;

		private const float BorderWidth = 2f;

		private static readonly Color BorderColour = Color.white;

		private bool _built;

		private bool _visible;

		public bool Visible => _visible;

		public Widget(PluginConfig cfg)
		{
			_cfg = cfg;
		}

		public void Show(Item item, Descriptions descriptions)
		{
			if (!_cfg.Enabled.Value)
			{
				Hide();
				return;
			}
			EnsureBuilt();
			string key = ((item.UIData != null) ? item.UIData.itemName : null);
			if (!descriptions.TryGet(key, out var info))
			{
				Hide();
				return;
			}
			Texture2D val = null;
			try
			{
				val = ((item.UIData != null) ? item.UIData.GetIcon() : null);
			}
			catch
			{
				val = null;
			}
			_icon.texture = (Texture)(object)val;
			((TMP_Text)_name).text = item.GetItemName((ItemInstanceData)null);
			((TMP_Text)_description).text = info.Description;
			((TMP_Text)_type).text = FormatTypes(info.Types, descriptions);
			((TMP_Text)_modifiers).text = ItemModifiers.Format(item);
			ApplyConfig();
			SetVisible(v: true);
		}

		public void Hide()
		{
			if (!_built)
			{
				_visible = false;
			}
			else
			{
				SetVisible(v: false);
			}
		}

		public void ApplyConfig()
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			if (_built)
			{
				_root.anchoredPosition = new Vector2(_cfg.OffsetX.Value, _cfg.OffsetY.Value);
				float value = _cfg.Scale.Value;
				((Transform)_root).localScale = new Vector3(value, value, 1f);
				_root.sizeDelta = new Vector2(_cfg.Width.Value, _root.sizeDelta.y);
				Color color = ((Graphic)_background).color;
				color.a = _cfg.BackgroundOpacity.Value;
				((Graphic)_background).color = color;
				_iconGo.SetActive(_cfg.ShowIcon.Value && (Object)(object)_icon.texture != (Object)null);
				((Component)_name).gameObject.SetActive(_cfg.ShowName.Value);
				((Component)_type).gameObject.SetActive(_cfg.ShowType.Value && !string.IsNullOrEmpty(((TMP_Text)_type).text));
				((Component)_description).gameObject.SetActive(_cfg.ShowDescription.Value);
				((Component)_modifiers).gameObject.SetActive(_cfg.ShowModifiers.Value && !string.IsNullOrEmpty(((TMP_Text)_modifiers).text));
				_iconLayout.preferredWidth = _cfg.IconSize.Value;
				_iconLayout.preferredHeight = _cfg.IconSize.Value;
				((TMP_Text)_name).fontSize = _cfg.NameFontSize.Value;
				((TMP_Text)_type).fontSize = _cfg.TypeFontSize.Value;
				((TMP_Text)_description).fontSize = _cfg.DescriptionFontSize.Value;
				((TMP_Text)_modifiers).fontSize = _cfg.ModifierFontSize.Value;
				LayoutRebuilder.ForceRebuildLayoutImmediate(_root);
			}
		}

		private void SetVisible(bool v)
		{
			_visible = v;
			if ((Object)(object)_rootGo != (Object)null)
			{
				_rootGo.SetActive(v);
			}
		}

		private void EnsureBuilt()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Expected O, but got Unknown
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_007e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0139: 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_018c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0196: Expected O, but got Unknown
			//IL_01e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e6: Expected O, but got Unknown
			//IL_0238: Unknown result type (might be due to invalid IL or missing references)
			//IL_0242: Expected O, but got Unknown
			//IL_02ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Unknown result type (might be due to invalid IL or missing references)
			//IL_0381: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_03e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_03ec: Expected O, but got Unknown
			//IL_0405: Unknown result type (might be due to invalid IL or missing references)
			//IL_0410: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0425: Unknown result type (might be due to invalid IL or missing references)
			//IL_044d: Unknown result type (might be due to invalid IL or missing references)
			//IL_048d: Unknown result type (might be due to invalid IL or missing references)
			if (!_built)
			{
				_canvasGo = new GameObject("PeakItemTooltipCanvas");
				Object.DontDestroyOnLoad((Object)(object)_canvasGo);
				Canvas obj = _canvasGo.AddComponent<Canvas>();
				obj.renderMode = (RenderMode)0;
				obj.sortingOrder = 5000;
				CanvasScaler obj2 = _canvasGo.AddComponent<CanvasScaler>();
				obj2.uiScaleMode = (ScaleMode)1;
				obj2.referenceResolution = new Vector2(1920f, 1080f);
				obj2.screenMatchMode = (ScreenMatchMode)0;
				obj2.matchWidthOrHeight = 0.5f;
				_rootGo = new GameObject("Widget");
				_rootGo.transform.SetParent(_canvasGo.transform, false);
				_root = _rootGo.AddComponent<RectTransform>();
				_root.anchorMin = new Vector2(0.5f, 0.5f);
				_root.anchorMax = new Vector2(0.5f, 0.5f);
				_root.pivot = new Vector2(0.5f, 0.5f);
				_background = _rootGo.AddComponent<ProceduralImage>();
				((Graphic)_background).color = new Color(0f, 0f, 0f, _cfg.BackgroundOpacity.Value);
				((Graphic)_background).raycastTarget = false;
				_rootGo.AddComponent<FreeModifier>().Radius = new Vector4(12f, 12f, 12f, 12f);
				VerticalLayoutGroup obj3 = _rootGo.AddComponent<VerticalLayoutGroup>();
				((LayoutGroup)obj3).padding = new RectOffset(12, 12, 10, 10);
				((HorizontalOrVerticalLayoutGroup)obj3).spacing = 6f;
				((HorizontalOrVerticalLayoutGroup)obj3).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)obj3).childControlHeight = true;
				((HorizontalOrVerticalLayoutGroup)obj3).childForceExpandWidth = true;
				((HorizontalOrVerticalLayoutGroup)obj3).childForceExpandHeight = false;
				((LayoutGroup)obj3).childAlignment = (TextAnchor)0;
				ContentSizeFitter obj4 = _rootGo.AddComponent<ContentSizeFitter>();
				obj4.horizontalFit = (FitMode)0;
				obj4.verticalFit = (FitMode)2;
				GameObject val = new GameObject("Header");
				val.transform.SetParent((Transform)(object)_root, false);
				val.AddComponent<RectTransform>();
				HorizontalLayoutGroup obj5 = val.AddComponent<HorizontalLayoutGroup>();
				((HorizontalOrVerticalLayoutGroup)obj5).spacing = 8f;
				((HorizontalOrVerticalLayoutGroup)obj5).childControlWidth = true;
				((HorizontalOrVerticalLayoutGroup)obj5).childControlHeight = true;
				((HorizontalOrVerticalLayoutGroup)obj5).childForceExpandWidth = false;
				((HorizontalOrVerticalLayoutGroup)obj5).childForceExpandHeight = false;
				((LayoutGroup)obj5).childAlignment = (TextAnchor)3;
				_iconGo = new GameObject("Icon");
				_iconGo.transform.SetParent(val.transform, false);
				_iconGo.AddComponent<RectTransform>();
				_icon = _iconGo.AddComponent<RawImage>();
				((Graphic)_icon).raycastTarget = false;
				_iconLayout = _iconGo.AddComponent<LayoutElement>();
				_iconLayout.preferredWidth = _cfg.IconSize.Value;
				_iconLayout.preferredHeight = _cfg.IconSize.Value;
				TMP_FontAsset gameFont = GetGameFont();
				_name = MakeText("Name", val.transform, gameFont, _cfg.NameFontSize.Value, (FontStyles)0, Color.white);
				((Component)_name).gameObject.AddComponent<LayoutElement>().flexibleWidth = 1f;
				_type = MakeText("Type", (Transform)(object)_root, gameFont, _cfg.TypeFontSize.Value, (FontStyles)2, TypeFallbackColour);
				((TMP_Text)_type).textWrappingMode = (TextWrappingModes)1;
				_description = MakeText("Description", (Transform)(object)_root, gameFont, _cfg.DescriptionFontSize.Value, (FontStyles)0, new Color(0.85f, 0.85f, 0.85f, 1f));
				((TMP_Text)_description).textWrappingMode = (TextWrappingModes)1;
				_modifiers = MakeText("Modifiers", (Transform)(object)_root, gameFont, _cfg.ModifierFontSize.Value, (FontStyles)0, Color.white);
				((TMP_Text)_modifiers).textWrappingMode = (TextWrappingModes)1;
				((TMP_Text)_modifiers).richText = true;
				GameObject val2 = new GameObject("Border");
				val2.transform.SetParent((Transform)(object)_root, false);
				RectTransform obj6 = val2.AddComponent<RectTransform>();
				obj6.anchorMin = Vector2.zero;
				obj6.anchorMax = Vector2.one;
				obj6.offsetMin = Vector2.zero;
				obj6.offsetMax = Vector2.zero;
				val2.AddComponent<LayoutElement>().ignoreLayout = true;
				_border = val2.AddComponent<ProceduralImage>();
				((Graphic)_border).color = BorderColour;
				_border.BorderWidth = 2f;
				((Graphic)_border).raycastTarget = false;
				val2.AddComponent<FreeModifier>().Radius = new Vector4(12f, 12f, 12f, 12f);
				_built = true;
				SetVisible(v: false);
			}
		}

		private static string FormatTypes(List<string> types, Descriptions descriptions)
		{
			//IL_003c: 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_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			if (types == null)
			{
				return "";
			}
			StringBuilder stringBuilder = new StringBuilder();
			bool flag = true;
			foreach (string type in types)
			{
				if (!string.IsNullOrEmpty(type))
				{
					Color colour;
					Color val = (descriptions.TryGetTypeColour(type, out colour) ? colour : TypeFallbackColour);
					if (!flag)
					{
						stringBuilder.Append(" / ");
					}
					flag = false;
					stringBuilder.Append("<color=#").Append(ColorUtility.ToHtmlStringRGB(val)).Append('>')
						.Append(type)
						.Append("</color>");
				}
			}
			return stringBuilder.ToString();
		}

		private static TextMeshProUGUI MakeText(string name, Transform parent, TMP_FontAsset font, float size, FontStyles style, Color colour)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0006: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0039: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name);
			val.transform.SetParent(parent, false);
			TextMeshProUGUI val2 = val.AddComponent<TextMeshProUGUI>();
			if ((Object)(object)font != (Object)null)
			{
				((TMP_Text)val2).font = font;
			}
			((TMP_Text)val2).fontSize = size;
			((TMP_Text)val2).fontStyle = style;
			((Graphic)val2).color = colour;
			((Graphic)val2).raycastTarget = false;
			return val2;
		}

		private static TMP_FontAsset GetGameFont()
		{
			if ((Object)(object)GUIManager.instance != (Object)null && (Object)(object)GUIManager.instance.interactNameText != (Object)null)
			{
				return ((TMP_Text)GUIManager.instance.interactNameText).font;
			}
			return null;
		}
	}
}