Decompiled source of Fishypedia v1.0.0

BepInEx/plugins/FishpediaStats.dll

Decompiled 4 days ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using FishNet.Object;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using TMPro;
using UnityEngine;
using UnityEngine.Localization.Components;
using UnityEngine.UI;

[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 FishpediaStats
{
	public static class BaitIndex
	{
		public struct BaitChance
		{
			public string Name;

			public float Chance;
		}

		private static readonly FieldInfo BaitNameField = AccessTools.Field(typeof(BaitInfo), "_name");

		private static Dictionary<byte, List<BaitChance>> _map;

		public static void Invalidate()
		{
			_map = null;
		}

		public static List<BaitChance> For(byte creatureId)
		{
			EnsureBuilt();
			if (_map != null && _map.TryGetValue(creatureId, out var value))
			{
				return value;
			}
			return null;
		}

		private static void EnsureBuilt()
		{
			if (_map != null)
			{
				return;
			}
			try
			{
				IReadOnlyList<BaitInfo> allBaits = GameInfo.AllBaits;
				if (allBaits == null || allBaits.Count == 0)
				{
					return;
				}
				Dictionary<byte, List<BaitChance>> dictionary = new Dictionary<byte, List<BaitChance>>();
				foreach (BaitInfo item in allBaits)
				{
					if ((Object)(object)item == (Object)null)
					{
						continue;
					}
					List<ItemInfoWeight> itemWeights = item.ItemWeights;
					if (itemWeights == null || itemWeights.Count == 0)
					{
						continue;
					}
					float num = 0f;
					foreach (ItemInfoWeight item2 in itemWeights)
					{
						if (!((Object)(object)((item2 != null) ? item2.Fishable : null) == (Object)null))
						{
							num += item2.Weight;
						}
					}
					if (num <= 0f)
					{
						continue;
					}
					string name = NameOf(item);
					Dictionary<byte, float> dictionary2 = new Dictionary<byte, float>();
					foreach (ItemInfoWeight item3 in itemWeights)
					{
						Fishable val = ((item3 != null) ? item3.Fishable : null);
						if (!((Object)(object)val == (Object)null))
						{
							Item itemToSpawn = val.ItemToSpawn;
							Creature val2 = (Creature)(object)((itemToSpawn is Creature) ? itemToSpawn : null);
							if (!((Object)(object)val2 == (Object)null))
							{
								byte iD = ((Item)val2).ID;
								dictionary2.TryGetValue(iD, out var value);
								dictionary2[iD] = value + item3.Weight;
							}
						}
					}
					foreach (KeyValuePair<byte, float> item4 in dictionary2)
					{
						if (!dictionary.TryGetValue(item4.Key, out var value2))
						{
							value2 = new List<BaitChance>();
							dictionary[item4.Key] = value2;
						}
						value2.Add(new BaitChance
						{
							Name = name,
							Chance = item4.Value / num
						});
					}
				}
				foreach (List<BaitChance> value3 in dictionary.Values)
				{
					value3.Sort((BaitChance a, BaitChance b) => b.Chance.CompareTo(a.Chance));
				}
				_map = dictionary;
				Plugin.Log.LogInfo((object)$"Bait index built: {dictionary.Count} creatures across {allBaits.Count} baits.");
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Could not build bait index: " + ex.Message));
				_map = new Dictionary<byte, List<BaitChance>>();
			}
		}

		private static string NameOf(BaitInfo bait)
		{
			try
			{
				string nameLocalized = bait.NameLocalized;
				if (!string.IsNullOrEmpty(nameLocalized))
				{
					return nameLocalized;
				}
			}
			catch
			{
			}
			try
			{
				if (BaitNameField?.GetValue(bait) is string text && !string.IsNullOrEmpty(text))
				{
					return text;
				}
			}
			catch
			{
			}
			return ((Object)bait).name;
		}

		public static string Describe(byte creatureId, bool withChance)
		{
			List<BaitChance> list = For(creatureId);
			if (list == null || list.Count == 0)
			{
				return null;
			}
			List<string> list2 = new List<string>(list.Count);
			foreach (BaitChance item in list)
			{
				if (!withChance)
				{
					list2.Add(item.Name);
					continue;
				}
				float num = item.Chance * 100f;
				string text = ((num >= 1f) ? $"{num:0}%" : "<1%");
				list2.Add(item.Name + " " + text);
			}
			return "Bait: " + string.Join(", ", list2);
		}
	}
	public static class JournalUI
	{
		private class SlotEntry
		{
			public JournalSlot Slot;

			public Creature Creature;

			public TextMeshProUGUI Inline;

			public RectTransform HoverRect;

			public Canvas Canvas;

			public Image Plaque;

			public Image Medal;

			public Image Nameplate;

			public bool TrophyBuilt;
		}

		private const string InlineTextName = "FishpediaStatsText";

		private const string FrameName = "FishpediaTrophyFrame";

		private const string OverlayName = "FishpediaTrophyOverlay";

		private const string PlateName = "FishpediaNameplate";

		private const string TooltipName = "FishpediaTooltip";

		private const float TooltipPadding = 12f;

		private static readonly FieldInfo WorthTextField = AccessTools.Field(typeof(JournalSlot), "_worthText");

		private static readonly FieldInfo ImageField = AccessTools.Field(typeof(JournalSlot), "_image");

		private static readonly FieldInfo ProgressTextField = AccessTools.Field(typeof(ThinkingUI), "_progressText");

		private static readonly List<SlotEntry> Entries = new List<SlotEntry>();

		private static ThinkingUI _thinkingUI;

		private static string _progressBaseText;

		private static RectTransform _tooltip;

		private static TextMeshProUGUI _tooltipText;

		private static Image _tooltipBg;

		private static Canvas _tooltipCanvas;

		private static Creature _tooltipFor;

		private static readonly NumberFormatInfo MoneyFormat = new NumberFormatInfo
		{
			CurrencySymbol = "$",
			CurrencyDecimalDigits = 0,
			CurrencyGroupSeparator = ",",
			CurrencyPositivePattern = 0,
			CurrencyNegativePattern = 1
		};

		public static void ApplyToSlot(JournalSlot slot, Creature creature)
		{
			try
			{
				if (!((Object)(object)slot == (Object)null))
				{
					SlotEntry entry = GetEntry(slot);
					entry.Creature = creature;
					object? obj = WorthTextField?.GetValue(slot);
					TextMeshProUGUI worth = (TextMeshProUGUI)((obj is TextMeshProUGUI) ? obj : null);
					object? obj2 = ImageField?.GetValue(slot);
					RawImage val = (RawImage)((obj2 is RawImage) ? obj2 : null);
					if ((Object)(object)entry.HoverRect == (Object)null && (Object)(object)val != (Object)null)
					{
						entry.HoverRect = ((Graphic)val).rectTransform;
						entry.Canvas = ((Graphic)val).canvas;
					}
					if (Plugin.ShowFrame.Value && (Object)(object)val != (Object)null)
					{
						EnsureTrophy(entry, val, worth);
					}
					UpdateTrophy(entry, creature);
					UpdateInline(entry, worth, creature);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Journal slot update failed: " + ex.Message));
			}
		}

		private static SlotEntry GetEntry(JournalSlot slot)
		{
			for (int num = Entries.Count - 1; num >= 0; num--)
			{
				if ((Object)(object)Entries[num].Slot == (Object)null)
				{
					Entries.RemoveAt(num);
				}
				else if (Entries[num].Slot == slot)
				{
					return Entries[num];
				}
			}
			SlotEntry slotEntry = new SlotEntry
			{
				Slot = slot
			};
			Entries.Add(slotEntry);
			return slotEntry;
		}

		public static void RegisterThinkingUI(ThinkingUI ui)
		{
			_thinkingUI = ui;
			_progressBaseText = null;
			BaitIndex.Invalidate();
		}

		public static void ApplyHint(ThinkingUI ui)
		{
			try
			{
				if ((Object)(object)ui == (Object)null)
				{
					ui = _thinkingUI;
				}
				if ((Object)(object)ui == (Object)null || ProgressTextField == null)
				{
					return;
				}
				object? value = ProgressTextField.GetValue(ui);
				TextMeshProUGUI val = (TextMeshProUGUI)((value is TextMeshProUGUI) ? value : null);
				if (!((Object)(object)val == (Object)null))
				{
					if (_progressBaseText == null)
					{
						_progressBaseText = ((TMP_Text)val).text;
					}
					((TMP_Text)val).text = _progressBaseText + "\n<size=70%>Hover a creature for details</size>";
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Journal hint failed: " + ex.Message));
			}
		}

		private static void EnsureTrophy(SlotEntry entry, RawImage image, TextMeshProUGUI worth)
		{
			//IL_0034: 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)
			//IL_0056: 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_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_015b: Unknown result type (might be due to invalid IL or missing references)
			//IL_015c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0182: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0202: Unknown result type (might be due to invalid IL or missing references)
			//IL_022e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0233: Unknown result type (might be due to invalid IL or missing references)
			if (entry.TrophyBuilt)
			{
				return;
			}
			entry.TrophyBuilt = true;
			RectTransform rectTransform = ((Graphic)image).rectTransform;
			Transform parent = ((Transform)rectTransform).parent;
			if (!((Object)(object)parent == (Object)null))
			{
				float value = Plugin.FramePadding.Value;
				Rect rect = rectTransform.rect;
				float num = Mathf.Max(((Rect)(ref rect)).width + value * 2f, 32f);
				rect = rectTransform.rect;
				float num2 = Mathf.Max(((Rect)(ref rect)).height + value * 2f, 32f);
				Replace(parent, "FishpediaTrophyFrame");
				RectTransform val = NewImage(parent, "FishpediaTrophyFrame", Color.white, TrophyArt.Plaque);
				CopyRect(rectTransform, val);
				Expand(val, value);
				((Transform)val).SetSiblingIndex(((Transform)rectTransform).GetSiblingIndex());
				entry.Plaque = ((Component)val).GetComponent<Image>();
				if (Plugin.ShowMedalForDrip.Value)
				{
					Replace(parent, "FishpediaTrophyOverlay");
					RectTransform component = new GameObject("FishpediaTrophyOverlay", new Type[1] { typeof(RectTransform) }).GetComponent<RectTransform>();
					((Transform)component).SetParent(parent, false);
					CopyRect(rectTransform, component);
					Expand(component, value);
					((Transform)component).SetAsLastSibling();
					float num3 = Mathf.Max(12f, num * Plugin.MedalScale.Value);
					RectTransform val2 = NewImage((Transform)(object)component, "Medal", Color.white, TrophyArt.Medal);
					Vector2 anchorMin = (val2.anchorMax = Vector2.one);
					val2.anchorMin = anchorMin;
					val2.pivot = Vector2.one;
					val2.sizeDelta = new Vector2(num3, num3 * 1.25f);
					val2.anchoredPosition = new Vector2((0f - num) * 0.07f, (0f - num2) * 0.07f);
					entry.Medal = ((Component)val2).GetComponent<Image>();
					((Behaviour)entry.Medal).enabled = false;
				}
				if (Plugin.ShowNameplate.Value && (Object)(object)worth != (Object)null)
				{
					RectTransform rectTransform2 = ((TMP_Text)worth).rectTransform;
					Replace(((Transform)rectTransform2).parent, "FishpediaNameplate");
					RectTransform val3 = NewImage(((Transform)rectTransform2).parent, "FishpediaNameplate", Color.white, TrophyArt.Nameplate);
					CopyRect(rectTransform2, val3);
					float w = num * Plugin.NameplateWidth.Value;
					rect = rectTransform2.rect;
					Resize(val3, rectTransform2, w, Mathf.Max(((Rect)(ref rect)).height, 18f) + 8f);
					((Transform)val3).SetSiblingIndex(((Transform)rectTransform2).GetSiblingIndex());
					entry.Nameplate = ((Component)val3).GetComponent<Image>();
				}
			}
		}

		private static void Replace(Transform parent, string name)
		{
			Transform val = (((Object)(object)parent != (Object)null) ? parent.Find(name) : null);
			if ((Object)(object)val != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)val).gameObject);
			}
		}

		private static void CopyRect(RectTransform src, RectTransform dst)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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_0026: 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_003e: 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)
			dst.anchorMin = src.anchorMin;
			dst.anchorMax = src.anchorMax;
			dst.pivot = src.pivot;
			((Transform)dst).localScale = ((Transform)src).localScale;
			((Transform)dst).localRotation = ((Transform)src).localRotation;
			dst.anchoredPosition = src.anchoredPosition;
			dst.sizeDelta = src.sizeDelta;
		}

		private static void Expand(RectTransform rt, float by)
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			//IL_000e: 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_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Unknown result type (might be due to invalid IL or missing references)
			rt.offsetMin -= new Vector2(by, by);
			rt.offsetMax += new Vector2(by, by);
		}

		private static void Resize(RectTransform rt, RectTransform reference, float w, float h)
		{
			//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_0018: Unknown result type (might be due to invalid IL or missing references)
			//IL_001d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0030: 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_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			Rect rect = reference.rect;
			float num = (((Rect)(ref rect)).width - w) * 0.5f;
			rect = reference.rect;
			float num2 = (((Rect)(ref rect)).height - h) * 0.5f;
			rt.offsetMin += new Vector2(num, num2);
			rt.offsetMax -= new Vector2(num, num2);
		}

		private static void UpdateTrophy(SlotEntry entry, Creature creature)
		{
			//IL_004a: 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)
			bool flag = (Object)(object)creature == (Object)null;
			if ((Object)(object)entry.Plaque != (Object)null)
			{
				((Behaviour)entry.Plaque).enabled = !flag;
				((Graphic)entry.Plaque).color = (Color)((!flag && IsDiscovered(creature)) ? Color.white : new Color(0.5f, 0.5f, 0.5f, 0.85f));
			}
			if ((Object)(object)entry.Nameplate != (Object)null)
			{
				((Behaviour)entry.Nameplate).enabled = !flag;
			}
			if ((Object)(object)entry.Medal != (Object)null)
			{
				((Behaviour)entry.Medal).enabled = !flag && (Plugin.AlwaysShowMedal.Value || HasDrip(creature));
			}
		}

		private static RectTransform NewImage(Transform parent, string name, Color color, Sprite sprite)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			GameObject val = new GameObject(name, new Type[1] { typeof(RectTransform) });
			RectTransform component = val.GetComponent<RectTransform>();
			((Transform)component).SetParent(parent, false);
			Image obj = val.AddComponent<Image>();
			obj.sprite = sprite;
			((Graphic)obj).color = color;
			((Graphic)obj).raycastTarget = false;
			obj.preserveAspect = false;
			return component;
		}

		public static void UpdateHover()
		{
			try
			{
				if (!PlayerThinking.IsThinking)
				{
					HideTooltip();
					return;
				}
				Creature creature;
				SlotEntry slotEntry = FindHovered(out creature);
				if (slotEntry == null || (Object)(object)creature == (Object)null)
				{
					HideTooltip();
				}
				else if (EnsureTooltip(slotEntry))
				{
					if (creature != _tooltipFor)
					{
						_tooltipFor = creature;
						SetTooltipText(BuildTooltip(creature));
					}
					((Component)_tooltip).gameObject.SetActive(true);
					PositionTooltip();
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Hover update failed: " + ex.Message));
				HideTooltip();
			}
		}

		private static SlotEntry FindHovered(out Creature creature)
		{
			//IL_0003: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0089: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			creature = null;
			Vector2 val = Vector2.op_Implicit(Input.mousePosition);
			for (int num = Entries.Count - 1; num >= 0; num--)
			{
				SlotEntry slotEntry = Entries[num];
				if ((Object)(object)slotEntry.Slot == (Object)null)
				{
					Entries.RemoveAt(num);
				}
				else if (!((Object)(object)slotEntry.Creature == (Object)null) && !((Object)(object)slotEntry.HoverRect == (Object)null) && ((Component)slotEntry.HoverRect).gameObject.activeInHierarchy)
				{
					Camera val2 = (((Object)(object)slotEntry.Canvas != (Object)null && (int)slotEntry.Canvas.renderMode != 0) ? slotEntry.Canvas.worldCamera : null);
					if (RectTransformUtility.RectangleContainsScreenPoint(slotEntry.HoverRect, val, val2))
					{
						creature = slotEntry.Creature;
						return slotEntry;
					}
				}
			}
			return null;
		}

		private static bool EnsureTooltip(SlotEntry anchor)
		{
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Expected O, but got Unknown
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_01b1: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ce: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ed: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)_tooltip != (Object)null)
			{
				return true;
			}
			object? obj = WorthTextField?.GetValue(anchor.Slot);
			TextMeshProUGUI val = (TextMeshProUGUI)((obj is TextMeshProUGUI) ? obj : null);
			if ((Object)(object)val == (Object)null)
			{
				return false;
			}
			Canvas val2 = (((Object)(object)anchor.Canvas != (Object)null) ? anchor.Canvas.rootCanvas : ((Graphic)val).canvas);
			if ((Object)(object)val2 == (Object)null)
			{
				return false;
			}
			_tooltipCanvas = val2;
			GameObject val3 = new GameObject("FishpediaTooltip", new Type[1] { typeof(RectTransform) });
			_tooltip = val3.GetComponent<RectTransform>();
			((Transform)_tooltip).SetParent(((Component)val2).transform, false);
			RectTransform tooltip = _tooltip;
			RectTransform tooltip2 = _tooltip;
			Vector2 val4 = default(Vector2);
			((Vector2)(ref val4))..ctor(0.5f, 0.5f);
			tooltip2.anchorMax = val4;
			tooltip.anchorMin = val4;
			_tooltip.pivot = new Vector2(0f, 1f);
			_tooltipBg = val3.AddComponent<Image>();
			((Graphic)_tooltipBg).color = new Color(0.04f, 0.04f, 0.05f, 0.92f);
			((Graphic)_tooltipBg).raycastTarget = false;
			GameObject val5 = Object.Instantiate<GameObject>(((Component)val).gameObject, (Transform)(object)_tooltip);
			((Object)val5).name = "Text";
			val5.SetActive(true);
			LocalizeStringEvent[] components = val5.GetComponents<LocalizeStringEvent>();
			for (int i = 0; i < components.Length; i++)
			{
				Object.Destroy((Object)(object)components[i]);
			}
			_tooltipText = val5.GetComponent<TextMeshProUGUI>();
			if ((Object)(object)_tooltipText == (Object)null)
			{
				Object.Destroy((Object)(object)val3);
				_tooltip = null;
				return false;
			}
			RectTransform rectTransform = ((TMP_Text)_tooltipText).rectTransform;
			((Vector2)(ref val4))..ctor(0f, 1f);
			rectTransform.anchorMax = val4;
			rectTransform.anchorMin = val4;
			rectTransform.pivot = new Vector2(0f, 1f);
			((Transform)rectTransform).localScale = Vector3.one;
			((Transform)rectTransform).localRotation = Quaternion.identity;
			rectTransform.anchoredPosition = new Vector2(12f, -12f);
			((TMP_Text)_tooltipText).fontSize = ((TMP_Text)val).fontSize * Plugin.TooltipFontScale.Value;
			((Graphic)_tooltipText).color = Color.white;
			((TMP_Text)_tooltipText).alignment = (TextAlignmentOptions)257;
			((TMP_Text)_tooltipText).richText = true;
			((Graphic)_tooltipText).raycastTarget = false;
			val3.transform.SetAsLastSibling();
			val3.SetActive(false);
			return true;
		}

		private static void SetTooltipText(string content)
		{
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.Max(120f, Plugin.TooltipWidth.Value);
			((TMP_Text)_tooltipText).text = content;
			float y = ((TMP_Text)_tooltipText).GetPreferredValues(content, num, 0f).y;
			((TMP_Text)_tooltipText).rectTransform.sizeDelta = new Vector2(num, y);
			_tooltip.sizeDelta = new Vector2(num + 24f, y + 24f);
		}

		private static void PositionTooltip()
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: Unknown result type (might be due to invalid IL or missing references)
			//IL_0056: 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_005f: 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_006e: 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_007b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0080: Unknown result type (might be due to invalid IL or missing references)
			//IL_0085: 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_008e: 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_00b8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: 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_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0115: Unknown result type (might be due to invalid IL or missing references)
			//IL_011c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0124: Unknown result type (might be due to invalid IL or missing references)
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0141: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			Transform transform = ((Component)_tooltipCanvas).transform;
			RectTransform val = (RectTransform)(object)((transform is RectTransform) ? transform : null);
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			Camera val2 = (((int)_tooltipCanvas.renderMode != 0) ? _tooltipCanvas.worldCamera : null);
			Vector2 val3 = default(Vector2);
			if (RectTransformUtility.ScreenPointToLocalPointInRectangle(val, Vector2.op_Implicit(Input.mousePosition), val2, ref val3))
			{
				Vector2 sizeDelta = _tooltip.sizeDelta;
				Rect rect = val.rect;
				Vector2 val4 = ((Rect)(ref rect)).size * 0.5f;
				Vector2 val5 = val3 + new Vector2(18f, -18f);
				if (val5.x + sizeDelta.x > val4.x)
				{
					val5.x = val3.x - 18f - sizeDelta.x;
				}
				if (val5.y - sizeDelta.y < 0f - val4.y)
				{
					val5.y = val3.y + 18f + sizeDelta.y;
				}
				val5.x = Mathf.Clamp(val5.x, 0f - val4.x, val4.x - sizeDelta.x);
				val5.y = Mathf.Clamp(val5.y, 0f - val4.y + sizeDelta.y, val4.y);
				_tooltip.anchoredPosition = val5;
			}
		}

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

		private static string BuildTooltip(Creature creature)
		{
			string currentSaveName = Plugin.CurrentSaveName;
			bool flag = !string.IsNullOrEmpty(currentSaveName);
			StringBuilder stringBuilder = new StringBuilder();
			stringBuilder.Append("<b>").Append(SafeName(creature)).Append("</b>");
			if (Plugin.HideForUndiscovered.Value && !IsDiscovered(creature))
			{
				stringBuilder.Append("\n<size=85%>Not discovered yet</size>");
				return stringBuilder.ToString();
			}
			FishStats fishStats = StatsStore.Get(((Item)creature).ID, global: true, null);
			FishStats fishStats2 = (flag ? StatsStore.Get(((Item)creature).ID, global: false, currentSaveName) : null);
			stringBuilder.Append('\n');
			if (flag)
			{
				stringBuilder.Append("<size=80%><pos=56%>All<pos=80%>Save</size>\n");
			}
			Row(stringBuilder, "Caught", (fishStats?.Caught ?? 0).ToString(), (fishStats2?.Caught ?? 0).ToString(), flag);
			Row(stringBuilder, "Sold", (fishStats?.Sold ?? 0).ToString(), (fishStats2?.Sold ?? 0).ToString(), flag);
			Row(stringBuilder, "Earned", Money(fishStats?.Money ?? 0), Money(fishStats2?.Money ?? 0), flag);
			Row(stringBuilder, "Deaths", (fishStats?.Deaths ?? 0).ToString(), (fishStats2?.Deaths ?? 0).ToString(), flag);
			if (Plugin.ShowBait.Value)
			{
				string value = BaitIndex.Describe(((Item)creature).ID, Plugin.ShowBaitChance.Value);
				if (!string.IsNullOrEmpty(value))
				{
					stringBuilder.Append("\n<size=85%>").Append(value).Append("</size>");
				}
			}
			return stringBuilder.ToString();
		}

		private static void Row(StringBuilder sb, string label, string all, string save, bool twoCol)
		{
			sb.Append(label);
			if (twoCol)
			{
				sb.Append("<pos=56%>").Append(all).Append("<pos=80%>")
					.Append(save);
			}
			else
			{
				sb.Append("<pos=56%>").Append(all);
			}
			sb.Append('\n');
		}

		private static string Money(long v)
		{
			return v.ToString("C0", MoneyFormat);
		}

		private static string SafeName(Creature c)
		{
			try
			{
				return ((Item)c).GetName() ?? "???";
			}
			catch
			{
				return "???";
			}
		}

		private static bool IsDiscovered(Creature creature)
		{
			try
			{
				return SaveManager.GetSavedCreature(creature)?.BeenKilled ?? false;
			}
			catch
			{
				return true;
			}
		}

		private static bool HasDrip(Creature creature)
		{
			try
			{
				SavedCreature savedCreature = SaveManager.GetSavedCreature(creature);
				return savedCreature != null && savedCreature.BeenKilled && savedCreature.KilledDrip;
			}
			catch
			{
				return false;
			}
		}

		private static void UpdateInline(SlotEntry entry, TextMeshProUGUI worth, Creature creature)
		{
			if (!Plugin.ShowInlineStats.Value)
			{
				if ((Object)(object)entry.Inline != (Object)null)
				{
					((TMP_Text)entry.Inline).text = "";
				}
				return;
			}
			if ((Object)(object)entry.Inline == (Object)null)
			{
				entry.Inline = CreateInline(worth);
				if ((Object)(object)entry.Inline == (Object)null)
				{
					return;
				}
			}
			((TMP_Text)entry.Inline).text = BuildInline(creature);
		}

		private static string BuildInline(Creature creature)
		{
			if ((Object)(object)creature == (Object)null)
			{
				return "";
			}
			if (Plugin.HideForUndiscovered.Value && !IsDiscovered(creature))
			{
				return "";
			}
			FishStats fishStats = StatsStore.Get(((Item)creature).ID, global: true, null);
			string text = $"Caught {fishStats?.Caught ?? 0}   Sold {fishStats?.Sold ?? 0}\n" + $"{Money(fishStats?.Money ?? 0)}   Deaths {fishStats?.Deaths ?? 0}";
			if (Plugin.ShowBait.Value)
			{
				string text2 = BaitIndex.Describe(((Item)creature).ID, Plugin.ShowBaitChance.Value);
				if (!string.IsNullOrEmpty(text2))
				{
					text = text + "\n" + text2;
				}
			}
			return text;
		}

		private static TextMeshProUGUI CreateInline(TextMeshProUGUI source)
		{
			//IL_00bf: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fe: Unknown result type (might be due to invalid IL or missing references)
			//IL_010a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0125: Unknown result type (might be due to invalid IL or missing references)
			//IL_012a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0143: Unknown result type (might be due to invalid IL or missing references)
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_0171: Unknown result type (might be due to invalid IL or missing references)
			//IL_0194: Unknown result type (might be due to invalid IL or missing references)
			//IL_0199: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d9: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)source == (Object)null)
			{
				return null;
			}
			Transform val = ((TMP_Text)source).transform.parent.Find("FishpediaStatsText");
			if ((Object)(object)val != (Object)null)
			{
				TextMeshProUGUI component = ((Component)val).GetComponent<TextMeshProUGUI>();
				if ((Object)(object)component != (Object)null)
				{
					return component;
				}
				Object.Destroy((Object)(object)((Component)val).gameObject);
			}
			GameObject val2 = Object.Instantiate<GameObject>(((Component)source).gameObject, ((TMP_Text)source).transform.parent);
			((Object)val2).name = "FishpediaStatsText";
			val2.SetActive(true);
			LocalizeStringEvent[] components = val2.GetComponents<LocalizeStringEvent>();
			for (int i = 0; i < components.Length; i++)
			{
				Object.Destroy((Object)(object)components[i]);
			}
			TextMeshProUGUI component2 = val2.GetComponent<TextMeshProUGUI>();
			if ((Object)(object)component2 == (Object)null)
			{
				Object.Destroy((Object)(object)val2);
				return null;
			}
			RectTransform rectTransform = ((TMP_Text)source).rectTransform;
			RectTransform rectTransform2 = ((TMP_Text)component2).rectTransform;
			rectTransform2.anchorMin = rectTransform.anchorMin;
			rectTransform2.anchorMax = rectTransform.anchorMax;
			((Transform)rectTransform2).localRotation = ((Transform)rectTransform).localRotation;
			((Transform)rectTransform2).localScale = ((Transform)rectTransform).localScale;
			rectTransform2.pivot = new Vector2(rectTransform.pivot.x, 1f);
			float num = Mathf.Max(rectTransform.sizeDelta.x * 2.8f, 240f);
			Rect rect = rectTransform.rect;
			rectTransform2.sizeDelta = new Vector2(num, Mathf.Max(((Rect)(ref rect)).height * 3.6f, 60f));
			rect = rectTransform.rect;
			float num2 = ((Rect)(ref rect)).height * (1f - rectTransform.pivot.y);
			rectTransform2.anchoredPosition = rectTransform.anchoredPosition + new Vector2(Plugin.ExtraOffsetX.Value, 0f - num2 - 4f + Plugin.ExtraOffsetY.Value);
			((TMP_Text)component2).fontSize = ((TMP_Text)source).fontSize * Plugin.TextFontScale.Value;
			((Graphic)component2).color = Plugin.ParseColor(Plugin.TextColor.Value, new Color(0.78f, 0.78f, 0.78f));
			((TMP_Text)component2).alignment = (TextAlignmentOptions)258;
			((TMP_Text)component2).richText = true;
			((Graphic)component2).raycastTarget = false;
			return component2;
		}
	}
	public static class Patches
	{
		private static readonly FieldInfo JointToBaitField = AccessTools.Field(typeof(Item), "_jointToBait");

		private static Creature _lastAttacker;

		private static float _lastAttackTime;

		private static string SafeName(Creature c)
		{
			try
			{
				return ((Item)c).GetName() ?? "";
			}
			catch
			{
				return "";
			}
		}

		private static void Record(Creature creature, Action<FishStats> apply)
		{
			if (!((Object)(object)creature == (Object)null))
			{
				StatsStore.Record(((Item)creature).ID, SafeName(creature), Plugin.CurrentSaveName, apply);
			}
		}

		private static bool IsLocal(Player player)
		{
			if ((Object)(object)player != (Object)null && (Object)(object)Player.LocalPlayer != (Object)null)
			{
				return (Object)(object)player == (Object)(object)Player.LocalPlayer;
			}
			return false;
		}

		[HarmonyPatch(typeof(Item), "InitializeBait")]
		[HarmonyPrefix]
		private static void Item_InitializeBait(Item __instance, FishingRod rod)
		{
			try
			{
				if ((Object)(object)rod == (Object)null || (Object)(object)((Item)rod).Holder == (Object)null || !((NetworkBehaviour)((Item)rod).Holder).Owner.IsLocalClient || (JointToBaitField != null && (Object)/*isinst with value type is only supported in some contexts*/ != (Object)null))
				{
					return;
				}
				Creature creature = __instance.Creature;
				if (!((Object)(object)creature == (Object)null))
				{
					Record(creature, delegate(FishStats s)
					{
						s.Caught++;
					});
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Catch tracking failed: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(MoneyManager), "SellItem")]
		[HarmonyPrefix]
		private static void MoneyManager_SellItem(Item item)
		{
			try
			{
				if ((Object)(object)MoneyManager.Instance == (Object)null || !((NetworkBehaviour)MoneyManager.Instance).IsServerInitialized || (Object)(object)item == (Object)null)
				{
					return;
				}
				Creature creature = item.Creature;
				if (!((Object)(object)creature == (Object)null) && IsLocal(item.LastHolder))
				{
					int worth = item.TotalWorth;
					Record(creature, delegate(FishStats s)
					{
						s.Sold++;
						s.Money += worth;
					});
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Sale tracking failed: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(AttackingFish), "DamageOnCollision", new Type[]
		{
			typeof(Player),
			typeof(Vector3)
		})]
		[HarmonyPostfix]
		private static void AttackingFish_DamageOnCollision(AttackingFish __instance, Player player)
		{
			NoteAttacker((Creature)(object)__instance, player);
		}

		[HarmonyPatch(typeof(BowheadWhale), "DamageOnCollision", new Type[]
		{
			typeof(Player),
			typeof(Vector3)
		})]
		[HarmonyPostfix]
		private static void BowheadWhale_DamageOnCollision(BowheadWhale __instance, Player player)
		{
			NoteAttacker((Creature)(object)__instance, player);
		}

		private static void NoteAttacker(Creature creature, Player player)
		{
			try
			{
				if (!((Object)(object)creature == (Object)null) && IsLocal(player))
				{
					_lastAttacker = creature;
					_lastAttackTime = Time.time;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Attacker tracking failed: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(PlayerDying), "DeathEffects")]
		[HarmonyPostfix]
		private static void PlayerDying_DeathEffects(PlayerDying __instance)
		{
			try
			{
				if (((NetworkBehaviour)__instance).Owner.IsLocalClient && !((Object)(object)_lastAttacker == (Object)null) && !(Time.time - _lastAttackTime > Plugin.DeathWindow.Value))
				{
					Record(_lastAttacker, delegate(FishStats s)
					{
						s.Deaths++;
					});
					_lastAttacker = null;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Death tracking failed: " + ex.Message));
			}
		}

		[HarmonyPatch(typeof(JournalSlot), "SetCreature")]
		[HarmonyPostfix]
		private static void JournalSlot_SetCreature(JournalSlot __instance, Creature creature)
		{
			JournalUI.ApplyToSlot(__instance, creature);
		}

		[HarmonyPatch(typeof(ThinkingUI), "SetProgressTexts")]
		[HarmonyPostfix]
		private static void ThinkingUI_SetProgressTexts(ThinkingUI __instance)
		{
			JournalUI.RegisterThinkingUI(__instance);
			JournalUI.ApplyHint(__instance);
		}

		[HarmonyPatch(typeof(ThinkingUI), "Update")]
		[HarmonyPostfix]
		private static void ThinkingUI_Update()
		{
			JournalUI.UpdateHover();
		}
	}
	[BepInPlugin("alexandre.howtofish.fishpediastats", "Fishypedia", "1.0.0")]
	public class Plugin : BaseUnityPlugin
	{
		public const string Guid = "alexandre.howtofish.fishpediastats";

		public static ManualLogSource Log;

		public static ConfigEntry<bool> HideForUndiscovered;

		public static ConfigEntry<bool> ShowBait;

		public static ConfigEntry<bool> ShowBaitChance;

		public static ConfigEntry<bool> ShowInlineStats;

		public static ConfigEntry<bool> ShowFrame;

		public static ConfigEntry<float> FramePadding;

		public static ConfigEntry<string> WoodDarkColor;

		public static ConfigEntry<string> WoodLightColor;

		public static ConfigEntry<string> WoodEdgeColor;

		public static ConfigEntry<bool> ShowMedalForDrip;

		public static ConfigEntry<bool> AlwaysShowMedal;

		public static ConfigEntry<string> MedalColor;

		public static ConfigEntry<string> MedalRibbonColor;

		public static ConfigEntry<float> MedalScale;

		public static ConfigEntry<bool> ShowNameplate;

		public static ConfigEntry<string> NameplateColor;

		public static ConfigEntry<string> NameplateEdgeColor;

		public static ConfigEntry<float> NameplateWidth;

		public static ConfigEntry<float> TooltipWidth;

		public static ConfigEntry<float> TooltipFontScale;

		public static ConfigEntry<float> ExtraOffsetX;

		public static ConfigEntry<float> ExtraOffsetY;

		public static ConfigEntry<float> TextFontScale;

		public static ConfigEntry<string> TextColor;

		public static ConfigEntry<float> DeathWindow;

		private const float FlushInterval = 5f;

		public static string CurrentSaveName
		{
			get
			{
				try
				{
					ServerSaveObject curServerSave = SaveManager.CurServerSave;
					return (curServerSave != null && !string.IsNullOrEmpty(curServerSave.Name)) ? curServerSave.Name : null;
				}
				catch
				{
					return null;
				}
			}
		}

		private void Awake()
		{
			//IL_0388: Unknown result type (might be due to invalid IL or missing references)
			Log = ((BaseUnityPlugin)this).Logger;
			HideForUndiscovered = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "HideForUndiscovered", true, "Hide stats for creatures still shown as '???', to avoid spoilers.");
			ShowBait = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowBait", true, "Show which bait catches each creature.");
			ShowBaitChance = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowBaitChance", true, "Include hook odds per bait. Turn off for just the bait names.");
			ShowInlineStats = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowInlineStats", false, "Also print the stats under each fish instead of only on hover. Enable this if you play on a gamepad, which has no mouse cursor in the journal.");
			ShowFrame = ((BaseUnityPlugin)this).Config.Bind<bool>("Trophy", "ShowFrame", true, "Mount each creature on a wooden trophy plaque.");
			FramePadding = ((BaseUnityPlugin)this).Config.Bind<float>("Trophy", "FramePadding", 14f, "How far the plaque extends beyond the creature image, in UI units.");
			WoodDarkColor = ((BaseUnityPlugin)this).Config.Bind<string>("Trophy", "WoodDarkColor", "4A2A13", "Hex RRGGBB of the dark wood grain. Takes effect after a restart.");
			WoodLightColor = ((BaseUnityPlugin)this).Config.Bind<string>("Trophy", "WoodLightColor", "A9743A", "Hex RRGGBB of the light wood grain. Takes effect after a restart.");
			WoodEdgeColor = ((BaseUnityPlugin)this).Config.Bind<string>("Trophy", "WoodEdgeColor", "2A1608", "Hex RRGGBB of the plaque's outer rim. Takes effect after a restart.");
			ShowMedalForDrip = ((BaseUnityPlugin)this).Config.Bind<bool>("Trophy", "ShowMedalForDrip", true, "Pin a medal in the corner of the plaque once you have caught a creature's shiny (drip) variant.");
			AlwaysShowMedal = ((BaseUnityPlugin)this).Config.Bind<bool>("Trophy", "AlwaysShowMedal", false, "Testing aid: show the medal on every creature, whether or not you have earned it.");
			MedalColor = ((BaseUnityPlugin)this).Config.Bind<string>("Trophy", "MedalColor", "E8C24A", "Hex RRGGBB of the medal's star. Takes effect after a restart.");
			MedalRibbonColor = ((BaseUnityPlugin)this).Config.Bind<string>("Trophy", "MedalRibbonColor", "C8102E", "Hex RRGGBB of the medal ribbon. Takes effect after a restart.");
			MedalScale = ((BaseUnityPlugin)this).Config.Bind<float>("Trophy", "MedalScale", 0.24f, "Medal width as a fraction of the plaque width.");
			ShowNameplate = ((BaseUnityPlugin)this).Config.Bind<bool>("Trophy", "ShowNameplate", true, "Show an engraved brass plate behind each creature's price.");
			NameplateColor = ((BaseUnityPlugin)this).Config.Bind<string>("Trophy", "NameplateColor", "C79A3A", "Hex RRGGBB of the nameplate. Takes effect after a restart.");
			NameplateEdgeColor = ((BaseUnityPlugin)this).Config.Bind<string>("Trophy", "NameplateEdgeColor", "5A4310", "Hex RRGGBB of the nameplate's rim. Takes effect after a restart.");
			NameplateWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Trophy", "NameplateWidth", 0.98f, "Nameplate width as a fraction of the plaque width.");
			TooltipWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Tooltip", "TooltipWidth", 340f, "Width of the hover tooltip in UI units.");
			TooltipFontScale = ((BaseUnityPlugin)this).Config.Bind<float>("Tooltip", "TooltipFontScale", 0.72f, "Tooltip font size as a fraction of the journal's price label.");
			ExtraOffsetX = ((BaseUnityPlugin)this).Config.Bind<float>("Inline", "ExtraOffsetX", 0f, "Horizontal nudge for the inline stats text (only used when ShowInlineStats is on).");
			ExtraOffsetY = ((BaseUnityPlugin)this).Config.Bind<float>("Inline", "ExtraOffsetY", 0f, "Vertical nudge for the inline stats text. Negative moves it down.");
			TextFontScale = ((BaseUnityPlugin)this).Config.Bind<float>("Inline", "TextFontScale", 0.62f, "Inline stats font size as a fraction of the price label.");
			TextColor = ((BaseUnityPlugin)this).Config.Bind<string>("Inline", "TextColor", "C8C8C8", "Hex RRGGBB colour of the inline stats text.");
			DeathWindow = ((BaseUnityPlugin)this).Config.Bind<float>("Tracking", "DeathAttributionWindow", 8f, "How many seconds after a creature hurts you it can still be blamed for your death.");
			StatsStore.Init(Path.Combine(Paths.ConfigPath, "FishpediaStats.json"));
			try
			{
				new Harmony("alexandre.howtofish.fishpediastats").PatchAll(typeof(Patches));
			}
			catch (Exception ex)
			{
				Log.LogError((object)("Failed to apply patches: " + ex));
			}
			Log.LogInfo((object)"Fishypedia loaded.");
		}

		private void Update()
		{
			StatsStore.Tick(Time.realtimeSinceStartup, 5f);
		}

		private void OnDestroy()
		{
			StatsStore.Flush();
		}

		private void OnApplicationQuit()
		{
			StatsStore.Flush();
		}

		public static Color ParseColor(string hex, Color fallback)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			Color result = default(Color);
			if (!string.IsNullOrEmpty(hex) && ColorUtility.TryParseHtmlString("#" + hex.TrimStart('#'), ref result))
			{
				return result;
			}
			return fallback;
		}
	}
	public class FishStats
	{
		public string Name = "";

		public int Caught;

		public int Sold;

		public long Money;

		public int Deaths;

		[JsonIgnore]
		public bool IsEmpty
		{
			get
			{
				if (Caught == 0 && Sold == 0 && Money == 0L)
				{
					return Deaths == 0;
				}
				return false;
			}
		}
	}
	public class StatsDocument
	{
		public int Version = 1;

		public Dictionary<byte, FishStats> Global = new Dictionary<byte, FishStats>();

		public Dictionary<string, Dictionary<byte, FishStats>> Saves = new Dictionary<string, Dictionary<byte, FishStats>>();
	}
	public static class StatsStore
	{
		private static StatsDocument _doc = new StatsDocument();

		private static string _path;

		private static bool _dirty;

		private static float _lastFlush;

		public static void Init(string path)
		{
			_path = path;
			Load();
		}

		private static void Load()
		{
			try
			{
				if (!File.Exists(_path))
				{
					return;
				}
				StatsDocument statsDocument = JsonConvert.DeserializeObject<StatsDocument>(File.ReadAllText(_path));
				if (statsDocument != null)
				{
					_doc = statsDocument;
					if (_doc.Global == null)
					{
						_doc.Global = new Dictionary<byte, FishStats>();
					}
					if (_doc.Saves == null)
					{
						_doc.Saves = new Dictionary<string, Dictionary<byte, FishStats>>();
					}
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Could not read stats file, starting fresh: " + ex.Message));
				TryBackupCorruptFile();
				_doc = new StatsDocument();
			}
		}

		private static void TryBackupCorruptFile()
		{
			try
			{
				if (File.Exists(_path))
				{
					File.Copy(_path, _path + ".corrupt", overwrite: true);
				}
			}
			catch
			{
			}
		}

		public static void MarkDirty()
		{
			_dirty = true;
		}

		public static void Tick(float time, float interval)
		{
			if (_dirty && !(time - _lastFlush < interval))
			{
				_lastFlush = time;
				Flush();
			}
		}

		public static void Flush()
		{
			if (!_dirty || _path == null)
			{
				return;
			}
			_dirty = false;
			try
			{
				string directoryName = Path.GetDirectoryName(_path);
				if (!string.IsNullOrEmpty(directoryName))
				{
					Directory.CreateDirectory(directoryName);
				}
				string text = _path + ".tmp";
				File.WriteAllText(text, JsonConvert.SerializeObject((object)_doc, (Formatting)1));
				if (File.Exists(_path))
				{
					File.Delete(_path);
				}
				File.Move(text, _path);
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Could not write stats file: " + ex.Message));
			}
		}

		private static FishStats GetOrAdd(Dictionary<byte, FishStats> table, byte id, string name)
		{
			if (!table.TryGetValue(id, out var value))
			{
				value = (table[id] = new FishStats());
			}
			if (!string.IsNullOrEmpty(name))
			{
				value.Name = name;
			}
			return value;
		}

		public static void Record(byte id, string name, string saveName, Action<FishStats> apply)
		{
			apply(GetOrAdd(_doc.Global, id, name));
			if (!string.IsNullOrEmpty(saveName))
			{
				if (!_doc.Saves.TryGetValue(saveName, out var value))
				{
					value = new Dictionary<byte, FishStats>();
					_doc.Saves[saveName] = value;
				}
				apply(GetOrAdd(value, id, name));
			}
			MarkDirty();
		}

		public static FishStats Get(byte id, bool global, string saveName)
		{
			if (global)
			{
				if (!_doc.Global.TryGetValue(id, out var value))
				{
					return null;
				}
				return value;
			}
			if (string.IsNullOrEmpty(saveName))
			{
				return null;
			}
			if (!_doc.Saves.TryGetValue(saveName, out var value2))
			{
				return null;
			}
			if (!value2.TryGetValue(id, out var value3))
			{
				return null;
			}
			return value3;
		}
	}
	public static class TrophyArt
	{
		public const float MedalAspect = 1.25f;

		private static Sprite _plaque;

		private static Sprite _medal;

		private static Sprite _nameplate;

		private const int Bands = 5;

		private static readonly Vector2[] StarPoly = BuildStarPoly(5, 1f, 0.42f);

		public static Sprite Plaque
		{
			get
			{
				if (!((Object)(object)_plaque != (Object)null))
				{
					return _plaque = Build(BuildPlaque);
				}
				return _plaque;
			}
		}

		public static Sprite Medal
		{
			get
			{
				if (!((Object)(object)_medal != (Object)null))
				{
					return _medal = Build(BuildMedal);
				}
				return _medal;
			}
		}

		public static Sprite Nameplate
		{
			get
			{
				if (!((Object)(object)_nameplate != (Object)null))
				{
					return _nameplate = Build(BuildNameplate);
				}
				return _nameplate;
			}
		}

		private static Sprite Build(Func<Sprite> f)
		{
			try
			{
				return f();
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Trophy art generation failed: " + ex.Message));
				return null;
			}
		}

		private static Sprite ToSprite(Texture2D tex)
		{
			//IL_0035: 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)
			((Texture)tex).filterMode = (FilterMode)1;
			((Texture)tex).wrapMode = (TextureWrapMode)1;
			((Object)tex).hideFlags = (HideFlags)61;
			tex.Apply();
			Sprite obj = Sprite.Create(tex, new Rect(0f, 0f, (float)((Texture)tex).width, (float)((Texture)tex).height), new Vector2(0.5f, 0.5f), 100f);
			((Object)obj).hideFlags = (HideFlags)61;
			return obj;
		}

		private static Sprite BuildPlaque()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0061: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: 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_007e: Expected O, but got Unknown
			//IL_01f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_015e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0155: Unknown result type (might be due to invalid IL or missing references)
			//IL_0156: Unknown result type (might be due to invalid IL or missing references)
			//IL_0157: Unknown result type (might be due to invalid IL or missing references)
			//IL_015f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0163: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Unknown result type (might be due to invalid IL or missing references)
			//IL_017b: Unknown result type (might be due to invalid IL or missing references)
			Color dark = Plugin.ParseColor(Plugin.WoodDarkColor.Value, new Color(0.29f, 0.16f, 0.07f));
			Color light = Plugin.ParseColor(Plugin.WoodLightColor.Value, new Color(0.66f, 0.45f, 0.23f));
			Color val = Plugin.ParseColor(Plugin.WoodEdgeColor.Value, new Color(0.16f, 0.09f, 0.03f));
			Texture2D val2 = new Texture2D(224, 224, (TextureFormat)4, false);
			Color[] array = (Color[])(object)new Color[50176];
			for (int i = 0; i < 224; i++)
			{
				for (int j = 0; j < 224; j++)
				{
					float num = 0f;
					float num2 = 0f;
					float num3 = 0f;
					float num4 = 0f;
					for (int k = 0; k < 3; k++)
					{
						for (int l = 0; l < 3; l++)
						{
							float num5 = ((float)j + ((float)l + 0.5f) / 3f) / 224f * 2f - 1f;
							float num6 = ((float)i + ((float)k + 0.5f) / 3f) / 224f * 2f - 1f;
							float num7 = Mathf.Pow(Mathf.Abs(num5), 3f) + Mathf.Pow(Mathf.Abs(num6), 3f);
							if (!(num7 > 1f))
							{
								Color val3 = ((Mathf.Pow(num7, 1f / 3f) > 0.945f) ? val : WoodAt(j, i, dark, light));
								num += val3.r;
								num2 += val3.g;
								num3 += val3.b;
								num4 += 1f;
							}
						}
					}
					array[i * 224 + j] = ((num4 <= 0f) ? new Color(0f, 0f, 0f, 0f) : new Color(num / num4, num2 / num4, num3 / num4, num4 / 9f));
				}
			}
			val2.SetPixels(array);
			return ToSprite(val2);
		}

		private static Color WoodAt(int x, int y, Color dark, Color light)
		{
			//IL_0076: Unknown result type (might be due to invalid IL or missing references)
			//IL_0077: Unknown result type (might be due to invalid IL or missing references)
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.PerlinNoise((float)x * 0.006f, (float)y * 0.05f);
			float num2 = Mathf.Sin((float)y * 0.22f + num * 3f);
			float num3 = 0.5f + 0.5f * num2;
			num3 = Mathf.Clamp01(num3 * 0.72f + Mathf.PerlinNoise((float)x * 0.02f, (float)y * 0.5f) * 0.28f);
			num3 = Mathf.Round(num3 * 4f) / 4f;
			return Color.Lerp(dark, light, num3);
		}

		private static Vector2[] BuildStarPoly(int points, float outer, float inner)
		{
			//IL_003b: 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)
			Vector2[] array = (Vector2[])(object)new Vector2[points * 2];
			for (int i = 0; i < array.Length; i++)
			{
				float num = MathF.PI / 2f + (float)i * MathF.PI / (float)points;
				float num2 = ((i % 2 == 0) ? outer : inner);
				array[i] = new Vector2(Mathf.Cos(num) * num2, Mathf.Sin(num) * num2);
			}
			return array;
		}

		private static bool InStar(float px, float py, float scale, float cx, float cy)
		{
			bool flag = false;
			int num = StarPoly.Length;
			int num2 = 0;
			int num3 = num - 1;
			while (num2 < num)
			{
				float num4 = cx + StarPoly[num2].x * scale;
				float num5 = cy + StarPoly[num2].y * scale;
				float num6 = cx + StarPoly[num3].x * scale;
				float num7 = cy + StarPoly[num3].y * scale;
				if (num5 > py != num7 > py && px < (num6 - num4) * (py - num5) / (num7 - num5) + num4)
				{
					flag = !flag;
				}
				num3 = num2++;
			}
			return flag;
		}

		private static Sprite BuildMedal()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			//IL_008d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d6: 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_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fc: Unknown result type (might be due to invalid IL or missing references)
			//IL_0103: Unknown result type (might be due to invalid IL or missing references)
			//IL_0105: Unknown result type (might be due to invalid IL or missing references)
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_010e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Unknown result type (might be due to invalid IL or missing references)
			//IL_0128: Expected O, but got Unknown
			//IL_036e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0353: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_0373: Unknown result type (might be due to invalid IL or missing references)
			//IL_02de: Unknown result type (might be due to invalid IL or missing references)
			//IL_02ea: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f6: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0201: Unknown result type (might be due to invalid IL or missing references)
			//IL_0203: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_02c2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d2: Unknown result type (might be due to invalid IL or missing references)
			//IL_02cf: Unknown result type (might be due to invalid IL or missing references)
			//IL_02d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0217: Unknown result type (might be due to invalid IL or missing references)
			//IL_021c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0251: Unknown result type (might be due to invalid IL or missing references)
			//IL_0258: Unknown result type (might be due to invalid IL or missing references)
			//IL_025d: Unknown result type (might be due to invalid IL or missing references)
			Color val = Plugin.ParseColor(Plugin.MedalColor.Value, new Color(0.91f, 0.76f, 0.29f));
			Color val2 = val * 0.62f;
			val2.a = 1f;
			Color val3 = val * 0.84f;
			val3.a = 1f;
			Color val4 = default(Color);
			((Color)(ref val4))..ctor(0.29f, 0.22f, 0.03f);
			Color val5 = Plugin.ParseColor(Plugin.MedalRibbonColor.Value, new Color(0.78f, 0.06f, 0.18f));
			Color val6 = default(Color);
			((Color)(ref val6))..ctor(0.11f, 0.25f, 0.55f);
			Color val7 = default(Color);
			((Color)(ref val7))..ctor(0.95f, 0.95f, 0.95f);
			float[] array = new float[7] { 0.1f, 0.4f, 0.44f, 0.56f, 0.6f, 0.9f, 1.01f };
			Color[] array2 = (Color[])(object)new Color[7] { val7, val5, val7, val6, val7, val5, val7 };
			Texture2D val8 = new Texture2D(128, 160, (TextureFormat)4, false);
			Color[] array3 = (Color[])(object)new Color[20480];
			float num = 0.8f;
			for (int i = 0; i < 160; i++)
			{
				for (int j = 0; j < 128; j++)
				{
					float num2 = 0f;
					float num3 = 0f;
					float num4 = 0f;
					float num5 = 0f;
					for (int k = 0; k < 3; k++)
					{
						for (int l = 0; l < 3; l++)
						{
							float num6 = ((float)j + ((float)l + 0.5f) / 3f) / 128f;
							float num7 = ((float)i + ((float)k + 0.5f) / 3f) / 160f;
							float num8 = (num6 - 0.5f) * num;
							float num9 = num7 - 0.5f;
							bool flag = false;
							Color val9 = default(Color);
							if (Mathf.Abs(num8) <= 0.2f && num9 >= 0.02f && num9 <= 0.5f)
							{
								float num10 = (num8 + 0.2f) / 0.4f;
								val9 = val7;
								for (int m = 0; m < array.Length; m++)
								{
									if (num10 <= array[m])
									{
										val9 = array2[m];
										break;
									}
								}
								if (0.2f - Mathf.Abs(num8) < 0.014f || 0.5f - num9 < 0.014f)
								{
									val9 *= 0.45f;
								}
								val9.a = 1f;
								flag = true;
							}
							if (InStar(num8, num9, 0.3f, 0f, -0.16f))
							{
								val9 = ((!InStar(num8, num9, 0.25800002f, 0f, -0.16f)) ? val4 : ((!InStar(num8, num9, 0.09f, 0f, -0.16f)) ? ((num9 > -0.19999999f) ? val : val3) : val2));
								flag = true;
							}
							if (flag)
							{
								num2 += val9.r;
								num3 += val9.g;
								num4 += val9.b;
								num5 += 1f;
							}
						}
					}
					array3[i * 128 + j] = ((num5 <= 0f) ? new Color(0f, 0f, 0f, 0f) : new Color(num2 / num5, num3 / num5, num4 / num5, num5 / 9f));
				}
			}
			val8.SetPixels(array3);
			return ToSprite(val8);
		}

		private static Sprite BuildNameplate()
		{
			//IL_0019: Unknown result type (might be due to invalid IL or missing references)
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Unknown result type (might be due to invalid IL or missing references)
			//IL_005a: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: Expected O, but got Unknown
			//IL_0221: Unknown result type (might be due to invalid IL or missing references)
			//IL_0206: Unknown result type (might be due to invalid IL or missing references)
			//IL_0226: 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_018d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0191: Unknown result type (might be due to invalid IL or missing references)
			//IL_019d: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_0189: Unknown result type (might be due to invalid IL or missing references)
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			Color val = Plugin.ParseColor(Plugin.NameplateColor.Value, new Color(0.78f, 0.6f, 0.23f));
			Color val2 = val * 0.82f;
			val2.a = 1f;
			Color val3 = Plugin.ParseColor(Plugin.NameplateEdgeColor.Value, new Color(0.35f, 0.26f, 0.06f));
			Texture2D val4 = new Texture2D(288, 64, (TextureFormat)4, false);
			Color[] array = (Color[])(object)new Color[18432];
			float num = 4.5f;
			for (int i = 0; i < 64; i++)
			{
				for (int j = 0; j < 288; j++)
				{
					float num2 = 0f;
					float num3 = 0f;
					float num4 = 0f;
					float num5 = 0f;
					for (int k = 0; k < 3; k++)
					{
						for (int l = 0; l < 3; l++)
						{
							float num6 = ((float)j + ((float)l + 0.5f) / 3f) / 288f;
							float num7 = ((float)i + ((float)k + 0.5f) / 3f) / 64f;
							float num8 = Mathf.Max(Mathf.Abs(num6 - 0.5f) * num - (0.5f * num - 0.16f), 0f);
							float num9 = Mathf.Max(Mathf.Abs(num7 - 0.5f) - 0.34f, 0f);
							if (!(Mathf.Sqrt(num8 * num8 + num9 * num9) > 0.16f))
							{
								Color val5 = ((Mathf.Min(Mathf.Min(num6, 1f - num6) * num, Mathf.Min(num7, 1f - num7)) < 0.09f) ? val3 : ((num7 > 0.5f) ? val : val2));
								num2 += val5.r;
								num3 += val5.g;
								num4 += val5.b;
								num5 += 1f;
							}
						}
					}
					array[i * 288 + j] = ((num5 <= 0f) ? new Color(0f, 0f, 0f, 0f) : new Color(num2 / num5, num3 / num5, num4 / num5, num5 / 9f));
				}
			}
			val4.SetPixels(array);
			return ToSprite(val4);
		}
	}
}