Decompiled source of TurnipSeedFinder v1.1.0

TurnipSeedFinder.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.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);
			}
		}
	}
}