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);
}
}
}
}