Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of FishQualityTracker v1.0.0
plugins/FishQualityTracker/FishQualityTracker.dll
Decompiled 9 hours agousing 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; } } }