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 TurnipSeedFinder v1.1.0
TurnipSeedFinder.dll
Decompiled 9 months agousing 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.Security; using System.Security.Permissions; using BepInEx; using HarmonyLib; using Microsoft.CodeAnalysis; using Splatform; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("0.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [Microsoft.CodeAnalysis.Embedded] [AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace TurnipSeedFinder { [BepInPlugin("FoobyScroobs.TurnipSeedFinder", "Turnip Seed Finder", "1.0.0")] public class BepInExPlugin : BaseUnityPlugin { public class GeneralConfig { public bool Enabled = true; public bool IsDebug = false; public float ScanRadius = 100f; public float ScanInterval = 5000f; public bool ShowLabels = true; public string TurnipSeedsLabel = "Turnip Seeds (Flower)"; } [HarmonyPatch(typeof(Humanoid), "Pickup")] private static class Pickup_Patch { private static void Postfix(Humanoid __instance, GameObject go, bool __result) { if (modEnabled && __result && !((Object)(object)__instance != (Object)(object)Player.m_localPlayer) && (Object)(object)go != (Object)null && isDebug && ((Object)go).name.Contains("SeedTurnip")) { Dbgl("*** PICKED UP TURNIP SEED: " + ((Object)go).name + " ***"); } } } [HarmonyPatch(typeof(Pickable), "Interact")] private static class Pickable_Interact_Patch { private static void Postfix(Pickable __instance, Humanoid character, bool repeat, bool __result) { if (modEnabled && __result && !((Object)(object)character != (Object)(object)Player.m_localPlayer) && isDebug && ((Object)__instance).name.Contains("SeedTurnip")) { Dbgl("*** INTERACTED WITH TURNIP SEED: " + ((Object)__instance).name + " ***"); } } } public static GeneralConfig General = new GeneralConfig(); private static string configFilePath; private static BepInExPlugin context; private static float lastScanTime = 0f; private static Dictionary<GameObject, PinData> turnipSeedPins = new Dictionary<GameObject, PinData>(); private static List<GameObject> trackedTurnipSeeds = new List<GameObject>(); public static bool modEnabled => General.Enabled; public static bool isDebug => General.IsDebug; public static float scanRadius => General.ScanRadius; public static float scanInterval => General.ScanInterval; public static bool showLabels => General.ShowLabels; public static string turnipSeedsLabel => General.TurnipSeedsLabel; private bool TryPreserveUserSettings() { try { if (!File.Exists(configFilePath)) { return false; } string[] array = File.ReadAllLines(configFilePath); bool result = false; string[] array2 = array; foreach (string text in array2) { string text2 = text.Trim(); if (string.IsNullOrEmpty(text2) || text2.StartsWith("#") || (text2.StartsWith("[") && text2.EndsWith("]")) || !text2.Contains("=")) { continue; } string[] array3 = text2.Split(new char[1] { '=' }, 2); if (array3.Length == 2) { string text3 = array3[0].Trim(); string text4 = array3[1].Trim(); int num = text4.IndexOf('#'); if (num >= 0) { text4 = text4.Substring(0, num).Trim(); } if (text4.StartsWith("\"") && text4.EndsWith("\"")) { text4 = text4.Substring(1, text4.Length - 2); } if (TryPreserveSetting(text3, text4)) { result = true; Debug.Log((object)("TurnipSeedFinder: Preserved setting " + text3 + " = '" + text4 + "'")); } } } return result; } catch (Exception ex) { Debug.LogWarning((object)("TurnipSeedFinder: Could not preserve user settings: " + ex.Message)); return false; } } private bool TryPreserveSetting(string key, string value) { try { switch (key) { case "Enabled": General.Enabled = ParseBool(value); return true; case "IsDebug": General.IsDebug = ParseBool(value); return true; case "ScanRadius": General.ScanRadius = ParseFloat(value); return true; case "ScanInterval": General.ScanInterval = ParseFloat(value); return true; case "ShowLabels": General.ShowLabels = ParseBool(value); return true; case "TurnipSeedsLabel": General.TurnipSeedsLabel = value; return true; default: return false; } } catch { return false; } } private void LoadConfig() { configFilePath = Path.Combine(Paths.ConfigPath, "FoobyScroobs.TurnipSeedFinder.cfg"); Dbgl("TurnipSeedFinder: Loading config from " + configFilePath); if (File.Exists(configFilePath)) { File.SetLastWriteTime(configFilePath, DateTime.Now); } if (!File.Exists(configFilePath)) { Dbgl("TurnipSeedFinder: Config file not found, creating default"); SaveConfig(); return; } try { string[] array = File.ReadAllLines(configFilePath); string text = ""; int num = 0; Dbgl($"TurnipSeedFinder: Read {array.Length} lines from config"); string[] array2 = array; foreach (string text2 in array2) { num++; string text3 = text2.Trim(); if (string.IsNullOrEmpty(text3) || text3.StartsWith("#")) { continue; } if (text3.StartsWith("[") && text3.EndsWith("]")) { text = text3.Substring(1, text3.Length - 2); Dbgl($"TurnipSeedFinder: Found section [{text}] at line {num}"); } else { if (!text3.Contains("=")) { continue; } string[] array3 = text3.Split(new char[1] { '=' }, 2); if (array3.Length == 2) { string text4 = array3[0].Trim(); string text5 = array3[1].Trim(); int num2 = text5.IndexOf('#'); if (num2 >= 0) { text5 = text5.Substring(0, num2).Trim(); } if (text5.StartsWith("\"") && text5.EndsWith("\"")) { text5 = text5.Substring(1, text5.Length - 2); } Dbgl("TurnipSeedFinder: Setting " + text + "." + text4 + " = '" + text5 + "'"); SetConfigValue(text, text4, text5); } } } Dbgl($"TurnipSeedFinder: Final config - ShowLabels: {General.ShowLabels}, ScanInterval: {General.ScanInterval}, Label: {General.TurnipSeedsLabel}"); } catch (Exception ex) { Debug.LogError((object)("TurnipSeedFinder: Error loading config: " + ex.Message + "\n" + ex.StackTrace)); if (TryPreserveUserSettings()) { Debug.Log((object)"TurnipSeedFinder: Preserved some user settings during config recovery"); } else { Debug.LogWarning((object)"TurnipSeedFinder: Could not preserve user settings, using defaults"); } SaveConfig(); } } private void SetConfigValue(string section, string key, string value) { try { if (section == "General") { switch (key) { case "Enabled": General.Enabled = ParseBool(value); break; case "IsDebug": General.IsDebug = ParseBool(value); break; case "ScanRadius": General.ScanRadius = ParseFloat(value); break; case "ScanInterval": General.ScanInterval = ParseFloat(value); break; case "ShowLabels": General.ShowLabels = ParseBool(value); break; case "TurnipSeedsLabel": General.TurnipSeedsLabel = value; break; } } } catch (Exception ex) { Debug.LogWarning((object)("Failed to set config value " + section + "." + key + " = " + value + ": " + ex.Message)); } } private void SaveConfig() { try { using StreamWriter streamWriter = new StreamWriter(configFilePath); streamWriter.WriteLine("; Turnip Seed Finder Configuration"); streamWriter.WriteLine("; This mod scans for turnip seed flowers and marks them on your minimap."); streamWriter.WriteLine("; Pins remove automatically when flowers are either picked by player, or destroyed."); streamWriter.WriteLine("; Not restricted to the swamp biome - will also find player-planted turnip flowers."); streamWriter.WriteLine(); streamWriter.WriteLine("[General]"); streamWriter.WriteLine(); streamWriter.WriteLine("; Set 'false' to disable this mod"); streamWriter.WriteLine("Enabled = " + General.Enabled.ToString().ToLower()); streamWriter.WriteLine(); streamWriter.WriteLine("; Set 'true' to display precise flower locations in console"); streamWriter.WriteLine("IsDebug = " + General.IsDebug.ToString().ToLower()); streamWriter.WriteLine(); streamWriter.WriteLine("; Radius in meters (how far to search for turnip seed flowers)"); streamWriter.WriteLine("ScanRadius = " + General.ScanRadius.ToString(CultureInfo.InvariantCulture)); streamWriter.WriteLine(); streamWriter.WriteLine("; Scan interval in milliseconds (5000 = 5 seconds)"); streamWriter.WriteLine("; Setting to 0 will scan every frame (not recommended, definite fps drop)"); streamWriter.WriteLine("ScanInterval = " + General.ScanInterval.ToString(CultureInfo.InvariantCulture)); streamWriter.WriteLine(); streamWriter.WriteLine("; Set 'false' to hide text labels on the minimap"); streamWriter.WriteLine("ShowLabels = " + General.ShowLabels.ToString().ToLower()); streamWriter.WriteLine(); streamWriter.WriteLine("; Customize your text for turnip seed flowers on the minimap"); streamWriter.WriteLine("TurnipSeedsLabel = \"" + General.TurnipSeedsLabel + "\""); } catch (Exception ex) { Debug.LogError((object)("Error saving config: " + ex.Message)); } } private bool ParseBool(string value) { return string.Equals(value, "true", StringComparison.OrdinalIgnoreCase); } private float ParseFloat(string value) { if (float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)) { return result; } return 0f; } public static void Dbgl(string str = "", bool pref = true) { if (isDebug) { Debug.Log((object)((pref ? (typeof(BepInExPlugin).Namespace + " ") : "") + str)); } } private void Awake() { context = this; LoadConfig(); Harmony.CreateAndPatchAll(typeof(BepInExPlugin), (string)null); Dbgl("Turnip Seed Finder mod loaded!"); } private void Update() { if (modEnabled && !((Object)(object)Player.m_localPlayer == (Object)null) && Time.timeScale != 0f) { float num = scanInterval / 1000f; if (Time.time - lastScanTime > num) { ScanForTurnipSeeds(); lastScanTime = Time.time; } UpdateTurnipSeedTracking(); } } private void ScanForTurnipSeeds() { //IL_0033: Unknown result type (might be due to invalid IL or missing references) //IL_0038: Unknown result type (might be due to invalid IL or missing references) //IL_004a: Unknown result type (might be due to invalid IL or missing references) //IL_0052: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)Player.m_localPlayer == (Object)null) { return; } Dbgl("=== SCANNING FOR TURNIP SEEDS ==="); GameObject[] array = Object.FindObjectsOfType<GameObject>(); int foundCount = 0; Vector3 position = ((Component)Player.m_localPlayer).transform.position; GameObject[] array2 = array; foreach (GameObject val in array2) { float num = Vector3.Distance(position, val.transform.position); if (num <= scanRadius && ((Object)val).name == "flower") { ProcessFlowerForTurnipSeeds(val, ref foundCount); } } Dbgl($"Total turnip seeds found: {foundCount}, Currently tracking: {trackedTurnipSeeds.Count}"); } private void ProcessFlowerForTurnipSeeds(GameObject flower, ref int foundCount) { //IL_0048: Unknown result type (might be due to invalid IL or missing references) Transform parent = flower.transform.parent; GameObject val = ((parent != null) ? ((Component)parent).gameObject : null); if ((Object)(object)val != (Object)null) { string name = ((Object)val).name; if (name.Contains("SeedTurnip")) { Dbgl($"Found turnip seed: {name} at position {flower.transform.position}"); foundCount++; Sprite turnipSeedIcon = GetTurnipSeedIcon(val); string pinName = (showLabels ? turnipSeedsLabel : ""); AddPinForTurnipSeed(flower, pinName, foundCount, turnipSeedIcon); } } } private Sprite GetTurnipSeedIcon(GameObject parentObject) { if ((Object)(object)parentObject == (Object)null) { return null; } Pickable component = parentObject.GetComponent<Pickable>(); if ((Object)(object)component != (Object)null && (Object)(object)component.m_itemPrefab != (Object)null) { ItemDrop component2 = component.m_itemPrefab.GetComponent<ItemDrop>(); if ((Object)(object)component2 != (Object)null && component2.m_itemData != null) { return component2.m_itemData.GetIcon(); } } return null; } private void AddPinForTurnipSeed(GameObject obj, string pinName, int objectNumber, Sprite customIcon) { //IL_007d: 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_0090: Unknown result type (might be due to invalid IL or missing references) //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_0053: Unknown result type (might be due to invalid IL or missing references) //IL_00c4: Unknown result type (might be due to invalid IL or missing references) if (!turnipSeedPins.ContainsKey(obj) && (Object)(object)Minimap.instance != (Object)null) { PinData val; if ((Object)(object)customIcon != (Object)null) { val = Minimap.instance.AddPin(obj.transform.position, (PinType)3, pinName, false, false, 0L, default(PlatformUserID)); val.m_icon = customIcon; val.m_worldSize = 0f; } else { val = Minimap.instance.AddPin(obj.transform.position, (PinType)1, pinName, false, false, 0L, default(PlatformUserID)); } val.m_name = pinName; turnipSeedPins[obj] = val; trackedTurnipSeeds.Add(obj); Dbgl($"Added pin for turnip seed at {obj.transform.position} with label '{pinName}'"); } } private void UpdateTurnipSeedTracking() { int num = 0; for (int num2 = trackedTurnipSeeds.Count - 1; num2 >= 0; num2--) { GameObject val = trackedTurnipSeeds[num2]; if ((Object)(object)val == (Object)null || !val.activeSelf) { if ((Object)(object)val != (Object)null && turnipSeedPins.ContainsKey(val)) { if ((Object)(object)Minimap.instance != (Object)null && turnipSeedPins[val] != null) { Minimap.instance.RemovePin(turnipSeedPins[val]); } turnipSeedPins.Remove(val); } trackedTurnipSeeds.RemoveAt(num2); num++; } } if (num > 0) { Dbgl($"Removed {num} turnip seed pins from tracking"); } List<GameObject> list = new List<GameObject>(); foreach (KeyValuePair<GameObject, PinData> turnipSeedPin in turnipSeedPins) { if ((Object)(object)turnipSeedPin.Key == (Object)null) { if ((Object)(object)Minimap.instance != (Object)null && turnipSeedPin.Value != null) { Minimap.instance.RemovePin(turnipSeedPin.Value); } list.Add(turnipSeedPin.Key); } } foreach (GameObject item in list) { turnipSeedPins.Remove(item); } } } }