Decompiled source of FishQualityTracker v1.0.0

plugins/FishQualityTracker/FishQualityTracker.dll

Decompiled 9 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("OceanMan1327")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyCopyright("Copyright (c) 2026 OceanMan1327")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("FishQualityTracker")]
[assembly: AssemblyTitle("FishQualityTracker")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace FishQualityTracker
{
	public static class BaitNames
	{
		public static string Resolve(string prefab, string sharedName, Func<string, string> localize)
		{
			string text = (prefab ?? "").Trim();
			if (text.EndsWith("(Clone)", StringComparison.Ordinal))
			{
				text = text.Substring(0, text.Length - 7).TrimEnd();
			}
			string text2 = null;
			string result = null;
			switch (text.ToLowerInvariant())
			{
			case "fishingbait":
				text2 = "item_fishingbait";
				result = "Fishing Bait";
				break;
			case "fishingbaitcave":
				text2 = "item_fishingbait_cave";
				result = "Cold Fishing Bait";
				break;
			case "fishingbaitswamp":
				text2 = "item_fishingbait_swamp";
				result = "Sticky Fishing Bait";
				break;
			case "fishingbaitforest":
				text2 = "item_fishingbait_forest";
				result = "Mossy Fishing Bait";
				break;
			case "fishingbaitplains":
				text2 = "item_fishingbait_plains";
				result = "Stingy Fishing Bait";
				break;
			case "fishingbaitocean":
				text2 = "item_fishingbait_ocean";
				result = "Heavy Fishing Bait";
				break;
			case "fishingbaitmistlands":
				text2 = "item_fishingbait_mistlands";
				result = "Misty Fishing Bait";
				break;
			case "fishingbaitashlands":
				text2 = "item_fishingbait_ashlands";
				result = "Hot Fishing Bait";
				break;
			case "fishingbaitdeepnorth":
				text2 = "item_fishingbait_deepnorth";
				result = "Frosty Fishing Bait";
				break;
			}
			if (text2 != null)
			{
				string text3 = localize?.Invoke("$" + text2);
				if (!string.IsNullOrWhiteSpace(text3) && !text3.Contains(text2))
				{
					return text3;
				}
				return result;
			}
			string text4 = (string.IsNullOrWhiteSpace(sharedName) ? text : (localize?.Invoke(sharedName) ?? sharedName));
			if (!string.IsNullOrWhiteSpace(text4))
			{
				return text4;
			}
			return "Bait?";
		}
	}
	public sealed class ConfigOrder
	{
		public int? Order { get; set; }
	}
	internal static class ConfigSectionOrder
	{
		private static Harmony harmony;

		public static void Install()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Expected O, but got Unknown
			//IL_007f: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Expected O, but got Unknown
			if (Chainloader.PluginInfos.TryGetValue("ModdedWolf.ModConfigs", out var value) && Object.op_Implicit((Object)(object)value.Instance))
			{
				MethodInfo methodInfo = ((object)value.Instance).GetType().Assembly.GetType("ModdedWolfsConfigs.ConfigDiscovery")?.GetMethod("Discover", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(methodInfo == null))
				{
					harmony = new Harmony("local.fishqualitytracker.configorder");
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(ConfigSectionOrder), "AfterDiscover", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				}
			}
		}

		private static void AfterDiscover(object __result)
		{
			if (!(__result is IEnumerable enumerable))
			{
				return;
			}
			foreach (object item in enumerable)
			{
				if (item == null)
				{
					continue;
				}
				Type type = item.GetType();
				if (!string.Equals(type.GetField("Guid")?.GetValue(item) as string, "local.fishqualitytracker", StringComparison.Ordinal) || !(type.GetField("Sections")?.GetValue(item) is IList list))
				{
					continue;
				}
				string[] obj = new string[5] { "Global", "Fish Nameplate", "ESP", "Filters", "Fish Types" };
				int num = 0;
				string[] array = obj;
				foreach (string text in array)
				{
					for (int j = num; j < list.Count; j++)
					{
						object obj2 = list[j];
						if (!(obj2?.GetType().GetField("Name")?.GetValue(obj2) as string != text))
						{
							list.RemoveAt(j);
							list.Insert(num++, obj2);
							break;
						}
					}
				}
				for (int k = 0; k < list.Count - 1; k++)
				{
					object obj3 = list[k];
					if (!(obj3?.GetType().GetField("Name")?.GetValue(obj3) as string != "Display"))
					{
						list.RemoveAt(k);
						list.Add(obj3);
						break;
					}
				}
			}
		}

		public static void Uninstall()
		{
			Harmony obj = harmony;
			if (obj != null)
			{
				obj.UnpatchSelf();
			}
			harmony = null;
		}
	}
	internal static class EspBox
	{
		private static readonly Vector3[] corners = (Vector3[])(object)new Vector3[8];

		public static bool TryBounds(Transform root, Renderer[] renderers, out Bounds bounds)
		{
			//IL_0001: 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_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0054: 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_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0071: Unknown result type (might be due to invalid IL or missing references)
			//IL_0076: 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_007d: 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_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Unknown result type (might be due to invalid IL or missing references)
			//IL_0096: Unknown result type (might be due to invalid IL or missing references)
			bounds = default(Bounds);
			bool flag = false;
			if (!Object.op_Implicit((Object)(object)root) || renderers == null)
			{
				return false;
			}
			foreach (Renderer val in renderers)
			{
				if (!Object.op_Implicit((Object)(object)val) || !((Component)val).gameObject.activeInHierarchy || (!(val is MeshRenderer) && !(val is SkinnedMeshRenderer)))
				{
					continue;
				}
				Bounds localBounds = val.localBounds;
				Matrix4x4 val2 = root.worldToLocalMatrix * val.localToWorldMatrix;
				for (int j = 0; j < 8; j++)
				{
					Vector3 val3 = ((Matrix4x4)(ref val2)).MultiplyPoint3x4(Corner(localBounds, j));
					if (Finite(val3))
					{
						if (!flag)
						{
							bounds = new Bounds(val3, Vector3.zero);
							flag = true;
						}
						else
						{
							((Bounds)(ref bounds)).Encapsulate(val3);
						}
					}
				}
			}
			if (flag)
			{
				Vector3 size = ((Bounds)(ref bounds)).size;
				return ((Vector3)(ref size)).sqrMagnitude > 1E-06f;
			}
			return false;
		}

		private static bool Finite(Vector3 p)
		{
			//IL_0000: 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_001a: Unknown result type (might be due to invalid IL or missing references)
			if (EspGeometry.Finite(p.x) && EspGeometry.Finite(p.y))
			{
				return EspGeometry.Finite(p.z);
			}
			return false;
		}

		private static Vector3 Corner(Bounds b, int i)
		{
			//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_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0031: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			return ((Bounds)(ref b)).center + Vector3.Scale(((Bounds)(ref b)).extents, new Vector3((float)(((i & 1) != 0) ? 1 : (-1)), (float)(((i & 2) != 0) ? 1 : (-1)), (float)(((i & 4) != 0) ? 1 : (-1))));
		}

		public static void Draw(Camera camera, Transform root, Bounds bounds, float padding, Color color, float thickness)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000b: Invalid comparison between Unknown and I4
			//IL_01d3: 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_0012: 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_0022: 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_0039: 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_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: 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_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00aa: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00af: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00da: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: 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_00ed: 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_00f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ff: 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_0118: Unknown result type (might be due to invalid IL or missing references)
			//IL_0127: Unknown result type (might be due to invalid IL or missing references)
			//IL_016b: 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_0178: Unknown result type (might be due to invalid IL or missing references)
			//IL_018e: Unknown result type (might be due to invalid IL or missing references)
			//IL_01ae: Unknown result type (might be due to invalid IL or missing references)
			if ((int)Event.current.type != 7)
			{
				return;
			}
			((Bounds)(ref bounds)).Expand(((Bounds)(ref bounds)).size * padding * 2f);
			for (int i = 0; i < 8; i++)
			{
				corners[i] = root.TransformPoint(Corner(bounds, i));
			}
			Matrix4x4 matrix = GUI.matrix;
			Color color2 = GUI.color;
			try
			{
				GUI.color = color;
				float near = Mathf.Max(0.01f, camera.nearClipPlane + 0.001f);
				Vector2 val5 = default(Vector2);
				for (int j = 0; j < EspGeometry.Edges.Length; j += 2)
				{
					Vector3 val = corners[EspGeometry.Edges[j]];
					Vector3 val2 = corners[EspGeometry.Edges[j + 1]];
					float z = camera.WorldToScreenPoint(val).z;
					float z2 = camera.WorldToScreenPoint(val2).z;
					if (!EspGeometry.ClipNear(z, z2, near, out var start, out var end))
					{
						continue;
					}
					Vector3 val3 = camera.WorldToScreenPoint(Vector3.Lerp(val, val2, start));
					Vector3 val4 = camera.WorldToScreenPoint(Vector3.Lerp(val, val2, end));
					float ax = val3.x;
					float ay = (float)Screen.height - val3.y;
					float bx = val4.x;
					float by = (float)Screen.height - val4.y;
					if (EspGeometry.ClipScreen(ref ax, ref ay, ref bx, ref by, Screen.width, Screen.height))
					{
						((Vector2)(ref val5))..ctor(bx - ax, by - ay);
						if (!(((Vector2)(ref val5)).sqrMagnitude < 0.01f))
						{
							GUI.matrix = matrix;
							GUIUtility.RotateAroundPivot(Mathf.Atan2(val5.y, val5.x) * 57.29578f, new Vector2(ax, ay));
							GUI.DrawTexture(new Rect(ax, ay - thickness / 2f, ((Vector2)(ref val5)).magnitude, thickness), (Texture)(object)Texture2D.whiteTexture);
						}
					}
				}
			}
			finally
			{
				GUI.matrix = matrix;
				GUI.color = color2;
			}
		}
	}
	public static class EspGeometry
	{
		public static readonly int[] Edges = new int[24]
		{
			0, 1, 2, 3, 4, 5, 6, 7, 0, 2,
			1, 3, 4, 6, 5, 7, 0, 4, 1, 5,
			2, 6, 3, 7
		};

		public static bool Finite(float value)
		{
			if (!float.IsNaN(value))
			{
				return !float.IsInfinity(value);
			}
			return false;
		}

		public static bool ClipNear(float az, float bz, float near, out float start, out float end)
		{
			start = 0f;
			end = 1f;
			if (!Finite(az) || !Finite(bz) || !Finite(near) || (az < near && bz < near))
			{
				return false;
			}
			if (az < near)
			{
				start = (near - az) / (bz - az);
			}
			else if (bz < near)
			{
				end = (near - az) / (bz - az);
			}
			return true;
		}

		public static bool ClipScreen(ref float ax, ref float ay, ref float bx, ref float by, float width, float height)
		{
			if (!Finite(ax) || !Finite(ay) || !Finite(bx) || !Finite(by) || width <= 0f || height <= 0f)
			{
				return false;
			}
			float num = bx - ax;
			float num2 = by - ay;
			float start = 0f;
			float end = 1f;
			if (!Finite(num) || !Finite(num2) || !Clip(0f - num, ax, ref start, ref end) || !Clip(num, width - ax, ref start, ref end) || !Clip(0f - num2, ay, ref start, ref end) || !Clip(num2, height - ay, ref start, ref end))
			{
				return false;
			}
			bx = ax + end * num;
			by = ay + end * num2;
			ax += start * num;
			ay += start * num2;
			return true;
		}

		private static bool Clip(float p, float q, ref float start, ref float end)
		{
			if (p == 0f)
			{
				return q >= 0f;
			}
			float num = q / p;
			if (p < 0f)
			{
				if (num > end)
				{
					return false;
				}
				if (num > start)
				{
					start = num;
				}
			}
			else
			{
				if (num < start)
				{
					return false;
				}
				if (num < end)
				{
					end = num;
				}
			}
			return true;
		}
	}
	public static class FishCaption
	{
		public static string Format(string name, int? quality, string bait, float distance, bool showName, bool showQuality, bool showBait, bool showDistance)
		{
			List<string> list = new List<string>(4);
			if (showName)
			{
				list.Add(name);
			}
			if (showQuality)
			{
				list.Add(quality.HasValue ? ("Q" + quality.Value) : "Q?");
			}
			if (showBait)
			{
				list.Add(string.IsNullOrEmpty(bait) ? "Bait?" : bait);
			}
			if (showDistance)
			{
				list.Add(distance.ToString("F0", CultureInfo.InvariantCulture) + " m");
			}
			return string.Join(" | ", list);
		}
	}
	public static class FishTypes
	{
		public static readonly string[] Names = new string[13]
		{
			"Perch", "Pike", "Tuna", "Tetra", "Trollfish", "Giant Herring", "Grouper", "Coral Cod", "Anglerfish", "Northern Salmon",
			"Magmafish", "Pufferfish", "Other Fish"
		};

		public static int Resolve(string rawName)
		{
			if (!string.IsNullOrWhiteSpace(rawName))
			{
				string a = rawName.Trim();
				for (int i = 0; i < Names.Length - 1; i++)
				{
					if (string.Equals(a, "$animal_fish" + (i + 1), StringComparison.OrdinalIgnoreCase) || string.Equals(a, Names[i], StringComparison.OrdinalIgnoreCase))
					{
						return i;
					}
				}
			}
			return Names.Length - 1;
		}
	}
	[BepInPlugin("local.fishqualitytracker", "FishQualityTracker", "1.0.0")]
	[BepInProcess("valheim.exe")]
	public sealed class Plugin : BaseUnityPlugin
	{
		private sealed class Entry
		{
			public Fish Fish;

			public Renderer[] Renderers;

			public string Internal;

			public string Name;

			public string Error;

			public string Bait = "Bait?";

			public int? Quality;

			public int TypeIndex = FishTypes.Names.Length - 1;

			public float Distance;

			public Vector3 Position;

			public string QualityText
			{
				get
				{
					if (!Quality.HasValue)
					{
						return "Q?";
					}
					return "Q" + Quality.Value;
				}
			}
		}

		private ConfigEntry<bool> active;

		private ConfigEntry<bool> hud;

		private ConfigEntry<bool> labels;

		private ConfigEntry<float> radius;

		private ConfigEntry<float> interval;

		private ConfigEntry<bool> espEnabled;

		private ConfigEntry<bool> showName;

		private ConfigEntry<bool> showQuality;

		private ConfigEntry<bool> showBait;

		private ConfigEntry<bool> showDistance;

		private ConfigEntry<float> espThickness;

		private ConfigEntry<float> espPadding;

		private ConfigEntry<string> espColor;

		private string lastEspColor;

		private Color boxColor = new Color(0f, 1f, 0.67f, 1f);

		private ConfigEntry<KeyboardShortcut> toggle;

		private ConfigEntry<KeyboardShortcut> espToggle;

		private ConfigEntry<string> qualities;

		private readonly ConfigEntry<bool>[] fishTypes = new ConfigEntry<bool>[FishTypes.Names.Length];

		private string lastQualityInput;

		private int qualityMask = 62;

		private readonly List<Entry> fish = new List<Entry>();

		private float nextScan;

		private float nextLog;

		private string status = "WAITING FOR PLAYER";

		private GUIStyle text;

		private GUIStyle label;

		private Vector2 scroll;

		private bool guiLogged;

		private void Awake()
		{
			//IL_00b2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Expected O, but got Unknown
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Expected O, but got Unknown
			//IL_0110: Unknown result type (might be due to invalid IL or missing references)
			//IL_011a: Expected O, but got Unknown
			//IL_012b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0135: Expected O, but got Unknown
			//IL_0146: Unknown result type (might be due to invalid IL or missing references)
			//IL_0150: Expected O, but got Unknown
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cd: Expected O, but got Unknown
			//IL_01de: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e8: Expected O, but got Unknown
			//IL_0235: Unknown result type (might be due to invalid IL or missing references)
			//IL_0274: Unknown result type (might be due to invalid IL or missing references)
			//IL_02f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_02fe: Expected O, but got Unknown
			//IL_030f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0319: Expected O, but got Unknown
			//IL_032a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0334: Expected O, but got Unknown
			//IL_0411: Unknown result type (might be due to invalid IL or missing references)
			//IL_041b: Expected O, but got Unknown
			//IL_043b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0461: Unknown result type (might be due to invalid IL or missing references)
			//IL_046b: Expected O, but got Unknown
			//IL_04c4: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ce: Expected O, but got Unknown
			//IL_0502: Unknown result type (might be due to invalid IL or missing references)
			//IL_050c: Expected O, but got Unknown
			//IL_0539: Unknown result type (might be due to invalid IL or missing references)
			//IL_0543: Expected O, but got Unknown
			//IL_03c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_039a: Unknown result type (might be due to invalid IL or missing references)
			//IL_03cb: Expected O, but got Unknown
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			ConfigEntry<bool> val = ((BaseUnityPlugin)this).Config.Bind<bool>("Scanner", "Enabled", true, (ConfigDescription)null);
			ConfigEntry<float> val2 = ((BaseUnityPlugin)this).Config.Bind<float>("Scanner", "ScanRadius", 250f, (ConfigDescription)null);
			ConfigEntry<float> val3 = ((BaseUnityPlugin)this).Config.Bind<float>("Scanner", "ScanInterval", 0.75f, (ConfigDescription)null);
			active = ((BaseUnityPlugin)this).Config.Bind<bool>("Global", "Enabled", val.Value, "Enable fish tracking.");
			radius = ((BaseUnityPlugin)this).Config.Bind<float>("Global", "ScanRadius", val2.Value, new ConfigDescription("Scan radius in metres.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 2000f), Array.Empty<object>()));
			interval = ((BaseUnityPlugin)this).Config.Bind<float>("Global", "ScanInterval", val3.Value, new ConfigDescription("Seconds between scans.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.1f, 10f), Array.Empty<object>()));
			((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("Scanner", "Enabled"));
			((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("Scanner", "ScanRadius"));
			((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("Scanner", "ScanInterval"));
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = false;
			((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowHud", false, (ConfigDescription)null);
			ConfigEntry<bool> val4 = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowDebugHud", false, (ConfigDescription)null);
			hud = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "Debug", val4.Value, "Show debug HUD and fish logs.");
			((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("Display", "ShowDebugHud"));
			((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("Display", "ShowHud"));
			ConfigEntry<bool> val5 = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowWorldLabels", true, (ConfigDescription)null);
			ConfigEntry<bool> val6 = ((BaseUnityPlugin)this).Config.Bind<bool>("Display", "ShowFishHud", true, (ConfigDescription)null);
			ConfigEntry<KeyboardShortcut> val7 = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("Display", "ToggleKey", new KeyboardShortcut((KeyCode)289, Array.Empty<KeyCode>()), (ConfigDescription)null);
			labels = BindNameplate("Enabled", val5.Value && val6.Value, "Show fish nameplates.");
			toggle = BindNameplate<KeyboardShortcut>("ToggleKey", val7.Value, "Toggle fish nameplates.");
			showName = BindNameplate("ShowName", defaultValue: true, "Show the fish name.");
			showQuality = BindNameplate("ShowQuality", defaultValue: true, "Show fish quality.");
			showBait = BindNameplate("ShowBait", defaultValue: true, "Show compatible bait.");
			showDistance = BindNameplate("ShowDistance", defaultValue: true, "Show distance to the player.");
			((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("Display", "ShowWorldLabels"));
			((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("Display", "ShowFishHud"));
			((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("Display", "ToggleKey"));
			qualities = ((BaseUnityPlugin)this).Config.Bind<string>("Filters", "QualityFilter", "1,2,3,4,5", "Qualities separated by commas. Empty = all.");
			RefreshQualityFilter();
			for (int i = 0; i < fishTypes.Length; i++)
			{
				fishTypes[i] = ((BaseUnityPlugin)this).Config.Bind<bool>("Fish Types", FishTypes.Names[i], true, (i == fishTypes.Length - 1) ? new ConfigDescription("For fish added with mods", (AcceptableValueBase)null, new object[1]
				{
					new ConfigOrder
					{
						Order = -1
					}
				}) : new ConfigDescription("", (AcceptableValueBase)null, Array.Empty<object>()));
			}
			espEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("ESP", "Enabled", true, new ConfigDescription("Show 3D fish boxes.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigOrder
				{
					Order = 20
				}
			}));
			espToggle = ((BaseUnityPlugin)this).Config.Bind<KeyboardShortcut>("ESP", "ToggleKey", new KeyboardShortcut((KeyCode)288, Array.Empty<KeyCode>()), new ConfigDescription("Toggle ESP boxes.", (AcceptableValueBase)null, new object[1]
			{
				new ConfigOrder
				{
					Order = 30
				}
			}));
			espColor = ((BaseUnityPlugin)this).Config.Bind<string>("ESP", "BoxColor", "#00FFAA", "Box color: #RRGGBB or #RRGGBBAA.");
			espThickness = ((BaseUnityPlugin)this).Config.Bind<float>("ESP", "LineThickness", 1.5f, new ConfigDescription("Line thickness in screen pixels.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.5f, 6f), Array.Empty<object>()));
			espPadding = ((BaseUnityPlugin)this).Config.Bind<float>("ESP", "BoxPadding", 0.05f, new ConfigDescription("Box padding (0.05 = 5%).", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 0.5f), Array.Empty<object>()));
			((BaseUnityPlugin)this).Config.Bind<bool>("ESP", "ThroughObstacles", true, (ConfigDescription)null);
			((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("ESP", "ThroughObstacles"));
			((BaseUnityPlugin)this).Config.SaveOnConfigSet = true;
			((BaseUnityPlugin)this).Config.Save();
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[FishQualityTracker] Config: " + ((BaseUnityPlugin)this).Config.ConfigFilePath));
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[FishQualityTracker] Plugin loaded");
			((BaseUnityPlugin)this).Logger.LogInfo((object)"[FishQualityTracker] Read-only scanner; Fish.Instances -> GetComponent<ItemDrop>() -> m_itemData.m_quality; optional Mod Configs UI ordering patch only.");
		}

		private ConfigEntry<T> BindNameplate<T>(string key, T defaultValue, string description)
		{
			//IL_0038: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Expected O, but got Unknown
			ConfigEntry<T> val = ((BaseUnityPlugin)this).Config.Bind<T>("Fish HUD", key, defaultValue, (ConfigDescription)null);
			ConfigEntry<T> result = ((BaseUnityPlugin)this).Config.Bind<T>("Fish Nameplate", key, val.Value, description);
			((BaseUnityPlugin)this).Config.Remove(new ConfigDefinition("Fish HUD", key));
			return result;
		}

		private void Start()
		{
			try
			{
				ConfigSectionOrder.Install();
			}
			catch (Exception ex)
			{
				((BaseUnityPlugin)this).Logger.LogWarning((object)("[FishQualityTracker] Could not reorder Mod Configs sections: " + ex.Message));
			}
		}

		private void Update()
		{
			//IL_0013: 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_0041: Unknown result type (might be due to invalid IL or missing references)
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			RefreshQualityFilter();
			if (!IsWorldHudBlocked())
			{
				KeyboardShortcut value = toggle.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					labels.Value = !labels.Value;
				}
				value = espToggle.Value;
				if (((KeyboardShortcut)(ref value)).IsDown())
				{
					espEnabled.Value = !espEnabled.Value;
				}
			}
			if (espColor.Value != lastEspColor)
			{
				lastEspColor = espColor.Value;
				Color val = default(Color);
				if (ColorUtility.TryParseHtmlString(lastEspColor, ref val))
				{
					boxColor = val;
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)"[FishQualityTracker] Invalid ESP BoxColor. Keeping the previous color.");
				}
			}
			if (!(Time.unscaledTime < nextScan))
			{
				nextScan = Time.unscaledTime + interval.Value;
				Scan();
			}
		}

		private void RefreshQualityFilter()
		{
			string text = qualities.Value ?? "";
			if (!(text == lastQualityInput))
			{
				lastQualityInput = text;
				if (QualityFilter.TryParse(text, out var mask))
				{
					qualityMask = mask;
				}
				else
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[FishQualityTracker] Invalid QualityFilter: '" + text + "'. Use 1–5 separated by commas. Keeping the last valid filter (all 1–5 at startup)."));
				}
			}
		}

		private static string ReadBait(Fish f)
		{
			List<string> list = new List<string>();
			if (f.m_baits == null)
			{
				return "Bait?";
			}
			foreach (BaitSetting bait2 in f.m_baits)
			{
				if (bait2 != null && bait2.m_chance > 0f && Object.op_Implicit((Object)(object)bait2.m_bait))
				{
					ItemDrop bait = bait2.m_bait;
					string item = BaitNames.Resolve(((Object)bait).name, bait.m_itemData?.m_shared?.m_name, (string key) => (Localization.instance == null) ? key : Localization.instance.Localize(key));
					if (!list.Contains(item))
					{
						list.Add(item);
					}
				}
			}
			if (list.Count != 0)
			{
				return string.Join(" / ", list);
			}
			return "Bait?";
		}

		private void Scan()
		{
			//IL_005c: 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_0098: Unknown result type (might be due to invalid IL or missing references)
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_009f: 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_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			fish.Clear();
			status = ((!active.Value) ? "DISABLED" : ((!Object.op_Implicit((Object)(object)Player.m_localPlayer)) ? "WAITING FOR PLAYER" : "ACTIVE"));
			if (status == "ACTIVE")
			{
				try
				{
					Vector3 position = ((Component)Player.m_localPlayer).transform.position;
					List<IMonoUpdater> instances = Fish.Instances;
					for (int i = 0; i < instances.Count; i++)
					{
						IMonoUpdater obj = instances[i];
						Fish val = (Fish)(object)((obj is Fish) ? obj : null);
						if (!Object.op_Implicit((Object)(object)val) || !((Behaviour)val).isActiveAndEnabled)
						{
							continue;
						}
						Vector3 position2 = ((Component)val).transform.position;
						float num = Vector3.Distance(position, position2);
						if (num > radius.Value)
						{
							continue;
						}
						Entry entry = new Entry
						{
							Fish = val,
							Internal = ((Object)val).name,
							Name = ((Object)val).name,
							Position = position2,
							Distance = num
						};
						fish.Add(entry);
						try
						{
							entry.Renderers = ((Component)val).GetComponentsInChildren<Renderer>(true);
							entry.TypeIndex = FishTypes.Resolve(val.m_name);
							if (!string.IsNullOrEmpty(val.m_name))
							{
								entry.Name = val.m_name;
							}
							ItemDrop component = ((Component)val).GetComponent<ItemDrop>();
							if (!Object.op_Implicit((Object)(object)component))
							{
								entry.Error = "ItemDrop component missing";
							}
							else if (component.m_itemData == null)
							{
								entry.Error = "ItemData missing";
							}
							else
							{
								entry.Quality = component.m_itemData.m_quality;
							}
							if (Localization.instance != null)
							{
								entry.Name = Localization.instance.Localize(entry.Name);
							}
						}
						catch (Exception ex)
						{
							entry.Error = ex.GetType().Name + ": " + ex.Message;
						}
						try
						{
							entry.Bait = ReadBait(val);
						}
						catch (Exception ex2)
						{
							entry.Error = ((entry.Error == null) ? "" : (entry.Error + "; ")) + "Bait: " + ex2.Message;
						}
					}
					fish.Sort((Entry a, Entry b) => a.Distance.CompareTo(b.Distance));
				}
				catch (Exception ex3)
				{
					status = "ERROR: " + ex3.GetType().Name;
				}
			}
			if (!hud.Value || Time.unscaledTime < nextLog)
			{
				return;
			}
			nextLog = Time.unscaledTime + 5f;
			((BaseUnityPlugin)this).Logger.LogInfo((object)("[FishQualityTracker] Scanner: " + status + " | Fish in range: " + fish.Count));
			foreach (Entry item in fish)
			{
				((BaseUnityPlugin)this).Logger.LogInfo((object)string.Format(CultureInfo.InvariantCulture, "[FishQualityTracker] {0} | Quality={1} | Distance={2:F1} | Position=({3:F1}, {4:F1}, {5:F1})", item.Internal, item.Quality.HasValue ? item.Quality.Value.ToString() : "?", item.Distance, item.Position.x, item.Position.y, item.Position.z));
				if (item.Error != null)
				{
					((BaseUnityPlugin)this).Logger.LogWarning((object)("[FishQualityTracker] Could not read fish data from " + item.Internal + ": " + item.Error));
				}
			}
		}

		private static bool IsWorldHudBlocked()
		{
			if (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || !Object.op_Implicit((Object)(object)ZNet.instance))
			{
				return true;
			}
			if (!Menu.IsVisible() && !Game.IsPaused() && (!Object.op_Implicit((Object)(object)Settings.instance) || !((Component)Settings.instance).gameObject.activeInHierarchy) && !Console.IsVisible() && !TextInput.IsVisible() && !StoreGui.IsVisible() && !Minimap.IsOpen())
			{
				if (Object.op_Implicit((Object)(object)TextViewer.instance))
				{
					return TextViewer.instance.IsVisible();
				}
				return false;
			}
			return true;
		}

		private void OnGUI()
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: 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_003c: Expected O, but got Unknown
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0070: Expected O, but got Unknown
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f4: Unknown result type (might be due to invalid IL or missing references)
			//IL_019f: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_01e2: 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_02d9: Invalid comparison between Unknown and I4
			//IL_03da: Unknown result type (might be due to invalid IL or missing references)
			//IL_03df: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f3: Unknown result type (might be due to invalid IL or missing references)
			//IL_03f9: Invalid comparison between Unknown and I4
			//IL_0458: Unknown result type (might be due to invalid IL or missing references)
			//IL_045a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0464: Unknown result type (might be due to invalid IL or missing references)
			//IL_0469: Unknown result type (might be due to invalid IL or missing references)
			//IL_046e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0473: Unknown result type (might be due to invalid IL or missing references)
			//IL_0475: Unknown result type (might be due to invalid IL or missing references)
			//IL_0486: Unknown result type (might be due to invalid IL or missing references)
			//IL_0424: Unknown result type (might be due to invalid IL or missing references)
			//IL_0432: Unknown result type (might be due to invalid IL or missing references)
			//IL_0497: Unknown result type (might be due to invalid IL or missing references)
			//IL_04a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_04ba: Unknown result type (might be due to invalid IL or missing references)
			//IL_04eb: Unknown result type (might be due to invalid IL or missing references)
			//IL_04f0: Unknown result type (might be due to invalid IL or missing references)
			//IL_0538: Unknown result type (might be due to invalid IL or missing references)
			//IL_053f: Expected O, but got Unknown
			//IL_0547: Unknown result type (might be due to invalid IL or missing references)
			//IL_0599: Unknown result type (might be due to invalid IL or missing references)
			//IL_05cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_05ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_05f3: Unknown result type (might be due to invalid IL or missing references)
			if (hud == null)
			{
				return;
			}
			if (this.text == null)
			{
				this.text = new GUIStyle(GUI.skin.label)
				{
					fontSize = 15,
					richText = false,
					wordWrap = false
				};
				this.text.normal.textColor = Color.white;
				label = new GUIStyle(this.text)
				{
					alignment = (TextAnchor)4,
					wordWrap = true
				};
			}
			if (hud.Value)
			{
				float num = Mathf.Min(610f, (float)Screen.width - 24f);
				float num2 = Mathf.Min(130f + (float)fish.Count * 46f, (float)Screen.height * 0.55f);
				GUI.Box(new Rect(12f, 12f, num, num2), GUIContent.none);
				GUILayout.BeginArea(new Rect(22f, 20f, num - 20f, num2 - 16f));
				GUILayout.Label("Fish Quality Tracker", this.text, Array.Empty<GUILayoutOption>());
				GUILayout.Label("Scanner: " + status + " | Radius: " + radius.Value.ToString("F0") + " m", this.text, Array.Empty<GUILayoutOption>());
				GUILayout.Label("Fish in range: " + fish.Count + " | " + ((object)toggle.Value/*cast due to .constrained prefix*/).ToString() + ": Fish HUD", this.text, Array.Empty<GUILayoutOption>());
				scroll = GUILayout.BeginScrollView(scroll, Array.Empty<GUILayoutOption>());
				foreach (Entry item in fish)
				{
					if (Object.op_Implicit((Object)(object)item.Fish))
					{
						GUILayout.Label(item.Name + " | " + item.QualityText + " | " + item.Distance.ToString("F0") + " m", this.text, Array.Empty<GUILayoutOption>());
						GUILayout.Label(item.Internal + " | " + ((Vector3)(ref item.Position)).ToString("F1"), this.text, Array.Empty<GUILayoutOption>());
					}
				}
				GUILayout.EndScrollView();
				GUILayout.EndArea();
				if (!guiLogged && (int)Event.current.type == 7)
				{
					guiLogged = true;
					((BaseUnityPlugin)this).Logger.LogInfo((object)("[FishQualityTracker] HUD rendered at " + Screen.width + "x" + Screen.height));
				}
			}
			if (!active.Value || (!labels.Value && !espEnabled.Value) || !Object.op_Implicit((Object)(object)Player.m_localPlayer) || IsWorldHudBlocked())
			{
				return;
			}
			Camera main = Camera.main;
			if (!Object.op_Implicit((Object)(object)main))
			{
				return;
			}
			foreach (Entry item2 in fish)
			{
				if (!Object.op_Implicit((Object)(object)item2.Fish) || !((Behaviour)item2.Fish).isActiveAndEnabled || !QualityFilter.Matches(qualityMask, item2.Quality) || !fishTypes[item2.TypeIndex].Value)
				{
					continue;
				}
				Vector3 position = ((Component)item2.Fish).transform.position;
				if (espEnabled.Value && (int)Event.current.type == 7 && EspBox.TryBounds(((Component)item2.Fish).transform, item2.Renderers, out var bounds))
				{
					EspBox.Draw(main, ((Component)item2.Fish).transform, bounds, espPadding.Value, boxColor, espThickness.Value);
				}
				if (!labels.Value)
				{
					continue;
				}
				Vector3 val = main.WorldToScreenPoint(position + Vector3.up * 0.6f);
				if (!(val.z <= 0f) && !(val.x < 0f) && !(val.x > (float)Screen.width) && !(val.y < 0f) && !(val.y > (float)Screen.height))
				{
					string text = FishCaption.Format(item2.Name, item2.Quality, item2.Bait, Vector3.Distance(((Component)Player.m_localPlayer).transform.position, position), showName.Value, showQuality.Value, showBait.Value, showDistance.Value);
					if (text.Length != 0)
					{
						GUIContent val2 = new GUIContent(text);
						float num3 = Mathf.Min(label.CalcSize(val2).x + 16f, (float)Mathf.Max(1, Screen.width - 16));
						float num4 = Mathf.Min((float)Screen.height, Mathf.Max(26f, label.CalcHeight(val2, num3) + 8f));
						Rect val3 = new Rect(Mathf.Clamp(val.x - num3 / 2f, 0f, Mathf.Max(0f, (float)Screen.width - num3)), Mathf.Clamp((float)Screen.height - val.y - num4, 0f, (float)Screen.height - num4), num3, num4);
						GUI.Box(val3, GUIContent.none);
						GUI.Label(val3, text, label);
					}
				}
			}
		}

		private void OnDestroy()
		{
			ConfigSectionOrder.Uninstall();
			fish.Clear();
		}
	}
	public static class QualityFilter
	{
		public static bool TryParse(string input, out int mask)
		{
			mask = 0;
			if (string.IsNullOrWhiteSpace(input))
			{
				return true;
			}
			string[] array = input.Split(',');
			for (int i = 0; i < array.Length; i++)
			{
				if (!int.TryParse(array[i].Trim(), NumberStyles.None, CultureInfo.InvariantCulture, out var result) || result < 1 || result > 5)
				{
					mask = 0;
					return false;
				}
				mask |= 1 << result;
			}
			return true;
		}

		public static bool Matches(int mask, int? quality)
		{
			if (quality.HasValue && mask != 0)
			{
				if (quality.Value >= 1 && quality.Value <= 5)
				{
					return (mask & (1 << quality.Value)) != 0;
				}
				return false;
			}
			return true;
		}
	}
}