Decompiled source of TrinketFortune v2.1.3

TrinketFortune.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using SunhavenMods.Shared;
using TrinketFortune.Patches;
using UnityEngine;
using UnityEngine.SceneManagement;
using Wish;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]
[assembly: AssemblyCompany("TrinketFortune")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+fe4c8b9eaa0b5ceabd85b506ee69e9e122723007")]
[assembly: AssemblyProduct("TrinketFortune")]
[assembly: AssemblyTitle("TrinketFortune")]
[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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[CompilerGenerated]
	[Embedded]
	[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = P_0;
		}
	}
	[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 SunhavenMods.Shared
{
	public static class ConfigFileHelper
	{
		public static ConfigFile CreateNamedConfig(string pluginGuid, string configFileName, Action<string> logWarning = null)
		{
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Expected O, but got Unknown
			string text = Path.Combine(Paths.ConfigPath, configFileName);
			string text2 = Path.Combine(Paths.ConfigPath, pluginGuid + ".cfg");
			try
			{
				if (!File.Exists(text) && File.Exists(text2))
				{
					File.Copy(text2, text);
				}
			}
			catch (Exception ex)
			{
				logWarning?.Invoke("[Config] Migration to " + configFileName + " failed: " + ex.Message);
			}
			return new ConfigFile(text, true);
		}

		public static bool ReplacePluginConfig(BaseUnityPlugin plugin, ConfigFile newConfig, Action<string> logWarning = null)
		{
			if ((Object)(object)plugin == (Object)null || newConfig == null)
			{
				return false;
			}
			try
			{
				Type typeFromHandle = typeof(BaseUnityPlugin);
				PropertyInfo property = typeFromHandle.GetProperty("Config", BindingFlags.Instance | BindingFlags.Public);
				if (property != null && property.CanWrite)
				{
					property.SetValue(plugin, newConfig, null);
					return true;
				}
				FieldInfo field = typeFromHandle.GetField("<Config>k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic);
				if (field != null)
				{
					field.SetValue(plugin, newConfig);
					return true;
				}
				FieldInfo[] fields = typeFromHandle.GetFields(BindingFlags.Instance | BindingFlags.NonPublic);
				foreach (FieldInfo fieldInfo in fields)
				{
					if (fieldInfo.FieldType == typeof(ConfigFile))
					{
						fieldInfo.SetValue(plugin, newConfig);
						return true;
					}
				}
			}
			catch (Exception ex)
			{
				logWarning?.Invoke("[Config] ReplacePluginConfig failed: " + ex.Message);
			}
			return false;
		}
	}
	public static class SharedCodeRevision
	{
		public const string Value = "2026.10.10";
	}
	public static class ModDiagnostics
	{
		private static readonly Dictionary<string, ModHealthReport> ReportsByPluginGuid = new Dictionary<string, ModHealthReport>(StringComparer.OrdinalIgnoreCase);

		private static readonly object Lock = new object();

		public static void ReportStartup(ModHealthReport report)
		{
			if (report == null || string.IsNullOrWhiteSpace(report.PluginGuid))
			{
				return;
			}
			report.ReportedUtc = DateTime.UtcNow;
			if (string.IsNullOrEmpty(report.SharedCodeRevision))
			{
				report.SharedCodeRevision = "2026.10.10";
			}
			lock (Lock)
			{
				ReportsByPluginGuid[report.PluginGuid] = report.Clone();
			}
		}

		public static void ReportRuntime(string pluginGuid, Action<ModHealthReport> update)
		{
			if (string.IsNullOrWhiteSpace(pluginGuid) || update == null)
			{
				return;
			}
			lock (Lock)
			{
				if (!ReportsByPluginGuid.TryGetValue(pluginGuid, out ModHealthReport value))
				{
					value = new ModHealthReport
					{
						PluginGuid = pluginGuid
					};
					ReportsByPluginGuid[pluginGuid] = value;
				}
				update(value);
				value.ReportedUtc = DateTime.UtcNow;
			}
		}

		public static ModHealthReport GetReport(string pluginGuid)
		{
			if (string.IsNullOrWhiteSpace(pluginGuid))
			{
				return null;
			}
			lock (Lock)
			{
				ModHealthReport value;
				return ReportsByPluginGuid.TryGetValue(pluginGuid, out value) ? value.Clone() : null;
			}
		}

		public static IReadOnlyList<ModHealthReport> GetAllReports()
		{
			lock (Lock)
			{
				return ReportsByPluginGuid.Values.Select((ModHealthReport r) => r.Clone()).ToList();
			}
		}

		public static string FormatHealthLogLine(ModHealthReport report)
		{
			if (report == null)
			{
				return "[Health] (empty report)";
			}
			string text = (string.IsNullOrEmpty(report.DisplayName) ? report.PluginGuid : report.DisplayName);
			string text2 = (string.IsNullOrEmpty(report.PluginVersion) ? "?" : report.PluginVersion);
			string text3 = (string.IsNullOrEmpty(report.SharedCodeRevision) ? "?" : report.SharedCodeRevision);
			string text4 = (string.IsNullOrEmpty(report.IntegrationSummary) ? "—" : report.IntegrationSummary);
			string text5 = (string.IsNullOrEmpty(report.Mode) ? "—" : report.Mode);
			string text6 = (string.IsNullOrEmpty(report.CharacterName) ? "—" : report.CharacterName);
			string text7 = ((!report.DataLoaded.HasValue) ? "—" : (report.DataLoaded.Value ? "loaded" : "none"));
			string text8 = (string.IsNullOrEmpty(report.LastPersistenceOutcome) ? "—" : report.LastPersistenceOutcome);
			return "[Health] " + text + " v" + text2 + " | shared " + text3 + " | integrations: " + text4 + " | mode: " + text5 + " | character: " + text6 + " | data: " + text7 + " | save: " + text8;
		}

		public static void LogStartupHealth(ManualLogSource log, ModHealthReport report)
		{
			ReportStartup(report);
			if (log != null)
			{
				log.LogInfo((object)FormatHealthLogLine(report));
			}
		}

		public static void LogModStartup(ManualLogSource log, string pluginGuid, string displayName, string pluginVersion, string integrationSummary, string mode = "startup", bool? dataLoaded = false, string lastPersistenceOutcome = "—")
		{
			LogStartupHealth(log, new ModHealthReport
			{
				PluginGuid = pluginGuid,
				DisplayName = displayName,
				PluginVersion = pluginVersion,
				SharedCodeRevision = "2026.10.10",
				IntegrationSummary = integrationSummary,
				Mode = mode,
				DataLoaded = dataLoaded,
				LastPersistenceOutcome = lastPersistenceOutcome
			});
		}
	}
	public sealed class ModHealthReport
	{
		public string PluginGuid { get; set; }

		public string DisplayName { get; set; }

		public string PluginVersion { get; set; }

		public string SharedCodeRevision { get; set; }

		public string IntegrationSummary { get; set; }

		public string Mode { get; set; }

		public string CharacterName { get; set; }

		public bool? DataLoaded { get; set; }

		public string LastPersistenceOutcome { get; set; }

		public string LastError { get; set; }

		public DateTime ReportedUtc { get; set; }

		public ModHealthReport Clone()
		{
			return new ModHealthReport
			{
				PluginGuid = PluginGuid,
				DisplayName = DisplayName,
				PluginVersion = PluginVersion,
				SharedCodeRevision = SharedCodeRevision,
				IntegrationSummary = IntegrationSummary,
				Mode = Mode,
				CharacterName = CharacterName,
				DataLoaded = DataLoaded,
				LastPersistenceOutcome = LastPersistenceOutcome,
				LastError = LastError,
				ReportedUtc = ReportedUtc
			};
		}

		public void AppendDiagnosticDump(StringBuilder sb)
		{
			if (sb != null)
			{
				sb.AppendLine("guid: " + (PluginGuid ?? "—"));
				sb.AppendLine("name: " + (DisplayName ?? "—"));
				sb.AppendLine("version: " + (PluginVersion ?? "—"));
				sb.AppendLine("shared: " + (SharedCodeRevision ?? "—"));
				sb.AppendLine("integrations: " + (IntegrationSummary ?? "—"));
				sb.AppendLine("mode: " + (Mode ?? "—"));
				sb.AppendLine("character: " + (string.IsNullOrEmpty(CharacterName) ? "—" : CharacterName));
				sb.AppendLine("data loaded: " + (DataLoaded.HasValue ? DataLoaded.Value.ToString() : "—"));
				sb.AppendLine("last save: " + (LastPersistenceOutcome ?? "—"));
				sb.AppendLine("last error: " + (LastError ?? "—"));
				sb.AppendLine("reported: " + ((ReportedUtc == default(DateTime)) ? "—" : ReportedUtc.ToLocalTime().ToString("u")));
			}
		}
	}
	public static class SuitePluginGuids
	{
		public const string DevTools = "com.azraelgodking.havendevtools";

		public const string SenpaisChest = "com.azraelgodking.senpaischest";

		public const string BirthdayReminder = "com.azraelgodking.squirrelsbirthdayreminder";

		public const string HavensBirthright = "com.azraelgodking.havensbirthright";

		public const string Smut = "com.azraelgodking.sunhavenmuseumutilitytracker";

		public const string SunhavenTodo = "com.azraelgodking.sunhaventodo";

		public const string TheVault = "com.azraelgodking.thevault";

		public const string HavensAlmanac = "com.azraelgodking.havensalmanac";

		public const string FasterRaces = "com.azraelgodking.fasterraces";

		public const string TrinketFortune = "com.azraelgodking.trinketfortune";

		public const string CropOptimizer = "com.azraelgodking.cropoptimizer";

		public const string HavensRespec = "com.azraelgodking.havensrespec";

		public const string GiftingAssistant = "com.azraelgodking.giftingassistant";

		public const string HavensMirror = "com.azraelgodking.havensmirror";
	}
	public static class ModHealthIntegrationSummary
	{
		public static string Build(params (string label, string pluginGuid)[] integrations)
		{
			if (integrations == null || integrations.Length == 0)
			{
				return "standalone";
			}
			Dictionary<string, PluginInfo> pluginInfos = Chainloader.PluginInfos;
			if (pluginInfos == null)
			{
				return "standalone";
			}
			List<string> list = new List<string>(integrations.Length);
			for (int i = 0; i < integrations.Length; i++)
			{
				var (text, text2) = integrations[i];
				if (!string.IsNullOrEmpty(text) && !string.IsNullOrEmpty(text2) && pluginInfos.ContainsKey(text2))
				{
					list.Add(text);
				}
			}
			if (list.Count != 0)
			{
				return string.Join(", ", list);
			}
			return "standalone";
		}
	}
	public static class ReflectionHelper
	{
		public static readonly BindingFlags AllBindingFlags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy;

		public static Type FindType(string typeName, params string[] namespaces)
		{
			Assembly[] assemblies;
			if (namespaces != null && namespaces.Length != 0)
			{
				string[] array = namespaces;
				for (int i = 0; i < array.Length; i++)
				{
					Type type = AccessTools.TypeByName(array[i] + "." + typeName);
					if (type != null)
					{
						return type;
					}
				}
				assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly in assemblies)
				{
					array = namespaces;
					foreach (string text in array)
					{
						try
						{
							Type type2 = assembly.GetType(text + "." + typeName, throwOnError: false);
							if (type2 != null)
							{
								return type2;
							}
						}
						catch
						{
						}
					}
				}
				assemblies = AppDomain.CurrentDomain.GetAssemblies();
				foreach (Assembly assembly2 in assemblies)
				{
					try
					{
						Type type3 = assembly2.GetTypes().FirstOrDefault((Type t) => namespaces.Any((string ns) => string.Equals(t.FullName, ns + "." + typeName, StringComparison.Ordinal) || (t.Name == typeName && string.Equals(t.Namespace, ns, StringComparison.Ordinal))));
						if (type3 != null)
						{
							return type3;
						}
					}
					catch (ReflectionTypeLoadException ex)
					{
						Type type4 = ex.Types?.FirstOrDefault((Type t) => t != null && namespaces.Any((string ns) => string.Equals(t.FullName, ns + "." + typeName, StringComparison.Ordinal) || (t.Name == typeName && string.Equals(t.Namespace, ns, StringComparison.Ordinal))));
						if (type4 != null)
						{
							return type4;
						}
					}
				}
				return null;
			}
			Type type5 = AccessTools.TypeByName(typeName);
			if (type5 != null)
			{
				return type5;
			}
			assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly3 in assemblies)
			{
				try
				{
					type5 = assembly3.GetTypes().FirstOrDefault((Type t) => t.Name == typeName || t.FullName == typeName);
					if (type5 != null)
					{
						return type5;
					}
				}
				catch (ReflectionTypeLoadException)
				{
				}
			}
			return null;
		}

		public static Type FindModPlugin(string assemblyName)
		{
			if (string.IsNullOrWhiteSpace(assemblyName))
			{
				return null;
			}
			Type type = FindType("Plugin", assemblyName);
			if (type != null && string.Equals(type.Assembly.GetName().Name, assemblyName, StringComparison.OrdinalIgnoreCase))
			{
				return type;
			}
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				if (!string.Equals(assembly.GetName().Name, assemblyName, StringComparison.OrdinalIgnoreCase))
				{
					continue;
				}
				Type type2 = assembly.GetType(assemblyName + ".Plugin", throwOnError: false);
				if (type2 != null)
				{
					return type2;
				}
				try
				{
					Type type3 = assembly.GetTypes().FirstOrDefault((Type t) => t.IsClass && !t.IsAbstract && t.Name == "Plugin");
					if (type3 != null)
					{
						return type3;
					}
				}
				catch (ReflectionTypeLoadException ex)
				{
					Type type4 = ex.Types?.FirstOrDefault((Type t) => t != null && t.IsClass && !t.IsAbstract && t.Name == "Plugin");
					if (type4 != null)
					{
						return type4;
					}
				}
			}
			return null;
		}

		public static MethodInfo GetStaticMethod(Type type, string methodName)
		{
			return type?.GetMethod(methodName, AllBindingFlags);
		}

		public static Type FindWishType(string typeName)
		{
			return FindType(typeName, "Wish");
		}

		public static object GetStaticValue(Type type, string memberName)
		{
			if (type == null)
			{
				return null;
			}
			try
			{
				PropertyInfo property = type.GetProperty(memberName, AllBindingFlags);
				if (property != null && property.GetMethod != null && property.GetIndexParameters().Length == 0)
				{
					return property.GetValue(null);
				}
			}
			catch (AmbiguousMatchException)
			{
				return null;
			}
			FieldInfo field = type.GetField(memberName, AllBindingFlags);
			if (field != null)
			{
				return field.GetValue(null);
			}
			return null;
		}

		public static object GetSingletonInstance(Type type)
		{
			if (type == null)
			{
				return null;
			}
			string[] array = new string[5] { "Instance", "instance", "_instance", "Singleton", "singleton" };
			foreach (string memberName in array)
			{
				object staticValue = GetStaticValue(type, memberName);
				if (staticValue != null)
				{
					return staticValue;
				}
			}
			return null;
		}

		public static object GetInstanceValue(object instance, string memberName)
		{
			if (instance == null)
			{
				return null;
			}
			Type type = instance.GetType();
			while (type != null)
			{
				PropertyInfo property = type.GetProperty(memberName, AllBindingFlags);
				if (property != null && property.GetMethod != null)
				{
					return property.GetValue(instance);
				}
				FieldInfo field = type.GetField(memberName, AllBindingFlags);
				if (field != null)
				{
					return field.GetValue(instance);
				}
				type = type.BaseType;
			}
			return null;
		}

		public static bool SetInstanceValue(object instance, string memberName, object value)
		{
			if (instance == null)
			{
				return false;
			}
			Type type = instance.GetType();
			while (type != null)
			{
				PropertyInfo property = type.GetProperty(memberName, AllBindingFlags);
				if (property != null && property.SetMethod != null)
				{
					property.SetValue(instance, value);
					return true;
				}
				FieldInfo field = type.GetField(memberName, AllBindingFlags);
				if (field != null)
				{
					field.SetValue(instance, value);
					return true;
				}
				type = type.BaseType;
			}
			return false;
		}

		public static object InvokeMethod(object instance, string methodName, params object[] args)
		{
			if (instance == null)
			{
				return null;
			}
			Type type = instance.GetType();
			Type[] array = args?.Select((object a) => a?.GetType() ?? typeof(object)).ToArray() ?? Type.EmptyTypes;
			MethodInfo methodInfo = AccessTools.Method(type, methodName, array, (Type[])null);
			if (methodInfo == null)
			{
				methodInfo = type.GetMethod(methodName, AllBindingFlags);
			}
			if (methodInfo == null)
			{
				return null;
			}
			return methodInfo.Invoke(instance, args);
		}

		public static object InvokeStaticMethod(Type type, string methodName, params object[] args)
		{
			if (type == null)
			{
				return null;
			}
			Type[] array = args?.Select((object a) => a?.GetType() ?? typeof(object)).ToArray() ?? Type.EmptyTypes;
			MethodInfo methodInfo = AccessTools.Method(type, methodName, array, (Type[])null);
			if (methodInfo == null)
			{
				methodInfo = type.GetMethod(methodName, AllBindingFlags);
			}
			if (methodInfo == null)
			{
				return null;
			}
			return methodInfo.Invoke(null, args);
		}

		public static FieldInfo[] GetAllFields(Type type)
		{
			if (type == null)
			{
				return Array.Empty<FieldInfo>();
			}
			FieldInfo[] fields = type.GetFields(AllBindingFlags);
			IEnumerable<FieldInfo> second;
			if (!(type.BaseType != null) || !(type.BaseType != typeof(object)))
			{
				second = Enumerable.Empty<FieldInfo>();
			}
			else
			{
				IEnumerable<FieldInfo> allFields = GetAllFields(type.BaseType);
				second = allFields;
			}
			return fields.Concat(second).Distinct().ToArray();
		}

		public static PropertyInfo[] GetAllProperties(Type type)
		{
			if (type == null)
			{
				return Array.Empty<PropertyInfo>();
			}
			PropertyInfo[] properties = type.GetProperties(AllBindingFlags);
			IEnumerable<PropertyInfo> second;
			if (!(type.BaseType != null) || !(type.BaseType != typeof(object)))
			{
				second = Enumerable.Empty<PropertyInfo>();
			}
			else
			{
				IEnumerable<PropertyInfo> allProperties = GetAllProperties(type.BaseType);
				second = allProperties;
			}
			return (from p in properties.Concat(second)
				group p by p.Name into g
				select g.First()).ToArray();
		}

		public static T TryGetValue<T>(object instance, string memberName, T defaultValue = default(T))
		{
			try
			{
				object instanceValue = GetInstanceValue(instance, memberName);
				if (instanceValue is T result)
				{
					return result;
				}
				if (instanceValue != null && typeof(T).IsAssignableFrom(instanceValue.GetType()))
				{
					return (T)instanceValue;
				}
				return defaultValue;
			}
			catch
			{
				return defaultValue;
			}
		}
	}
	public static class ReflectionProbe
	{
		private static readonly HashSet<string> Reported = new HashSet<string>(StringComparer.Ordinal);

		private static readonly object Lock = new object();

		public static bool Try(string site, Action action, ManualLogSource log = null)
		{
			if (action == null)
			{
				return false;
			}
			try
			{
				action();
				return true;
			}
			catch (Exception ex)
			{
				bool flag;
				lock (Lock)
				{
					flag = Reported.Add(site ?? "unknown");
				}
				if (flag && log != null)
				{
					log.LogWarning((object)("[Probe] " + site + " failed (" + ex.GetType().Name + ": " + ex.Message + ") — game version drift?"));
				}
				return false;
			}
		}

		public static bool Try<T>(string site, Func<T> func, out T result, ManualLogSource log = null)
		{
			result = default(T);
			if (func == null)
			{
				return false;
			}
			try
			{
				result = func();
				return true;
			}
			catch (Exception ex)
			{
				bool flag;
				lock (Lock)
				{
					flag = Reported.Add(site ?? "unknown");
				}
				if (flag && log != null)
				{
					log.LogWarning((object)("[Probe] " + site + " failed (" + ex.GetType().Name + ": " + ex.Message + ") — game version drift?"));
				}
				return false;
			}
		}

		public static void LogOnce(string site, Exception ex, ManualLogSource log = null)
		{
			bool flag;
			lock (Lock)
			{
				flag = Reported.Add(site ?? "unknown");
			}
			if (flag)
			{
				string text = ((ex != null) ? (ex.GetType().Name + ": " + ex.Message) : "unknown error");
				if (log != null)
				{
					log.LogWarning((object)("[Probe] " + site + " failed (" + text + ") — game version drift?"));
				}
			}
		}

		public static void ResetReportedSitesForTests()
		{
			lock (Lock)
			{
				Reported.Clear();
			}
		}
	}
}
namespace TrinketFortune
{
	public static class Config
	{
		public static ConfigEntry<bool> Enabled;

		public static ConfigEntry<float> MuseumProgressBonusPercent;

		public static ConfigEntry<float> MinimumMuseumProgress;

		public static ConfigEntry<float> MaxBonusChancePercent;

		public static void Bind(ConfigFile config)
		{
			//IL_0044: Unknown result type (might be due to invalid IL or missing references)
			//IL_004e: Expected O, but got Unknown
			//IL_007c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Expected O, but got Unknown
			//IL_00b4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Expected O, but got Unknown
			Enabled = config.Bind<bool>("General", "Enabled", true, "Enable Trinket Fortune. When enabled, odds of unowned fishing trinkets increase as you complete the aquarium.");
			MuseumProgressBonusPercent = config.Bind<float>("General", "MuseumProgressBonusPercent", 5f, new ConfigDescription("Bonus to unowned trinket/fish odds per 10% aquarium completion (e.g. 5 = +5% per 10%). Applied on top of base drop chance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 50f), Array.Empty<object>()));
			MinimumMuseumProgress = config.Bind<float>("General", "MinimumMuseumProgress", 0.2f, new ConfigDescription("Museum progress below this has no bonus (0.2 = 20% donated). Prevents bonus at very low completion.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			MaxBonusChancePercent = config.Bind<float>("General", "MaxBonusChancePercent", 75f, new ConfigDescription("Maximum bonus chance cap (%). Clamps the computed bonus regardless of aquarium progress. E.g. 75 = never more than a 75% bonus chance.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0f, 100f), Array.Empty<object>()));
		}
	}
	public static class DonationHelper
	{
		private const string SmutGuid = "com.azraelgodking.sunhavenmuseumutilitytracker";

		private static object _donationManager;

		private static MethodInfo _hasDonatedByGameId;

		private static MethodInfo _getSectionStatsMethod;

		private static MethodInfo _getAllSectionsMethod;

		private static object _aquariumSection;

		private static float _lastResolveAttemptRealtime;

		private const float ResolveRetrySeconds = 10f;

		private static FieldInfo _lootLevelField;

		private static PropertyInfo _lootLevelProperty;

		private static bool _lootLevelResolved;

		private static bool _lootLevelLoggedMissing;

		public static bool IsAvailable
		{
			get
			{
				EnsureResolved();
				if (_donationManager != null)
				{
					return _hasDonatedByGameId != null;
				}
				return false;
			}
		}

		static DonationHelper()
		{
			_lastResolveAttemptRealtime = -100f;
			EnsureResolved(force: true);
		}

		private static void EnsureResolved(bool force = false)
		{
			if (!force && _donationManager != null && _hasDonatedByGameId != null)
			{
				return;
			}
			float realtimeSinceStartup = Time.realtimeSinceStartup;
			if (!force && realtimeSinceStartup - _lastResolveAttemptRealtime < 10f)
			{
				return;
			}
			_lastResolveAttemptRealtime = realtimeSinceStartup;
			if (Chainloader.PluginInfos == null || !Chainloader.PluginInfos.TryGetValue("com.azraelgodking.sunhavenmuseumutilitytracker", out var value) || (Object)(object)((value != null) ? value.Instance : null) == (Object)null)
			{
				return;
			}
			try
			{
				MethodInfo method = ((object)value.Instance).GetType().GetMethod("GetDonationManager", BindingFlags.Static | BindingFlags.Public);
				if (!(method == null))
				{
					_donationManager = method.Invoke(null, null);
					if (_donationManager != null)
					{
						_hasDonatedByGameId = _donationManager.GetType().GetMethod("HasDonatedByGameId", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(int) }, null);
					}
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)("DonationHelper: SMUT bind failed: " + ex.Message));
				}
			}
		}

		public static bool HasDonatedByGameId(int gameItemId)
		{
			EnsureResolved();
			if (_donationManager == null || _hasDonatedByGameId == null)
			{
				return false;
			}
			try
			{
				return (bool)_hasDonatedByGameId.Invoke(_donationManager, new object[1] { gameItemId });
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)$"DonationHelper: HasDonatedByGameId failed for {gameItemId}: {ex.Message}");
				}
				return false;
			}
		}

		public static int PickBiasedFishingMuseumItem()
		{
			if (!Config.Enabled.Value)
			{
				return 0;
			}
			List<int> fishingMuseumItems = FishingRod.fishingMuseumItems;
			if (fishingMuseumItems == null || fishingMuseumItems.Count == 0)
			{
				return 0;
			}
			if (!IsAvailable)
			{
				return 0;
			}
			List<int> list = new List<int>(fishingMuseumItems.Count);
			for (int i = 0; i < fishingMuseumItems.Count; i++)
			{
				int num = fishingMuseumItems[i];
				if (!HasDonatedByGameId(num))
				{
					list.Add(num);
				}
			}
			if (list.Count == 0)
			{
				return fishingMuseumItems[Random.Range(0, fishingMuseumItems.Count)];
			}
			float aquariumProgress = GetAquariumProgress();
			if (aquariumProgress < Config.MinimumMuseumProgress.Value * 100f)
			{
				return fishingMuseumItems[Random.Range(0, fishingMuseumItems.Count)];
			}
			float num2 = Mathf.Min(Config.MuseumProgressBonusPercent.Value * (aquariumProgress / 10f), Config.MaxBonusChancePercent.Value);
			if (Random.Range(0f, 100f) < num2)
			{
				return list[Random.Range(0, list.Count)];
			}
			return fishingMuseumItems[Random.Range(0, fishingMuseumItems.Count)];
		}

		public static float GetAquariumProgressPercent()
		{
			return GetAquariumProgress();
		}

		private static float GetAquariumProgress()
		{
			if (TryGetSmutAquariumProgress(out var percent))
			{
				return percent;
			}
			return GetGameSaveAquariumProgress();
		}

		private static bool TryGetSmutAquariumProgress(out float percent)
		{
			percent = 0f;
			EnsureResolved();
			if (_donationManager == null)
			{
				return false;
			}
			try
			{
				EnsureAquariumSectionResolved();
				if (_aquariumSection == null || _getSectionStatsMethod == null)
				{
					return false;
				}
				object obj = _getSectionStatsMethod.Invoke(_donationManager, new object[1] { _aquariumSection });
				if (obj == null)
				{
					return false;
				}
				Type type = obj.GetType();
				FieldInfo fieldInfo = type.GetField("Item1") ?? type.GetField("donated");
				FieldInfo fieldInfo2 = type.GetField("Item2") ?? type.GetField("total");
				if (fieldInfo == null || fieldInfo2 == null)
				{
					return false;
				}
				int num = (int)fieldInfo.GetValue(obj);
				int num2 = (int)fieldInfo2.GetValue(obj);
				if (num2 <= 0)
				{
					return false;
				}
				percent = (float)num / (float)num2 * 100f;
				return true;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)("DonationHelper: SMUT aquarium progress failed: " + ex.Message));
				}
				return false;
			}
		}

		private static void EnsureAquariumSectionResolved()
		{
			if ((_aquariumSection != null && _getSectionStatsMethod != null) || _donationManager == null)
			{
				return;
			}
			Type type = _donationManager.GetType();
			_getSectionStatsMethod = type.GetMethod("GetSectionStats", BindingFlags.Instance | BindingFlags.Public);
			if (_getSectionStatsMethod == null)
			{
				return;
			}
			Type type2 = type.Assembly.GetType("SunHavenMuseumUtilityTracker.Data.MuseumContent");
			if (type2 == null)
			{
				return;
			}
			_getAllSectionsMethod = type2.GetMethod("GetAllSections", BindingFlags.Static | BindingFlags.Public);
			if (!(_getAllSectionsMethod?.Invoke(null, null) is IEnumerable enumerable))
			{
				return;
			}
			foreach (object item in enumerable)
			{
				if (item != null && string.Equals(item.GetType().GetProperty("Id")?.GetValue(item) as string, "aquarium", StringComparison.OrdinalIgnoreCase))
				{
					_aquariumSection = item;
					break;
				}
			}
		}

		private static float GetGameSaveAquariumProgress()
		{
			try
			{
				int num = 0;
				int num2 = 0;
				Type type = Type.GetType("Wish.GameSave, SunHaven.Core");
				if (type == null)
				{
					return 0f;
				}
				PropertyInfo property = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public);
				if (property == null)
				{
					return 0f;
				}
				object value = property.GetValue(null);
				if (value == null)
				{
					return 0f;
				}
				MethodInfo method = type.GetMethod("GetProgressIntWorld", new Type[1] { typeof(string) });
				if (method == null)
				{
					return 0f;
				}
				foreach (var item2 in MuseumCurator.aquaticMuseumProgress)
				{
					string text = item2.Item1 + "complete";
					int item = item2.Item2;
					int num3 = (int)method.Invoke(value, new object[1] { text });
					num += item;
					num2 += num3;
				}
				return (num > 0) ? ((float)num2 / (float)num * 100f) : 0f;
			}
			catch (Exception ex)
			{
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)("DonationHelper: aquarium progress fallback used due to reflection error: " + ex.Message));
				}
				return 0f;
			}
		}

		public static FishData PickBiasedFish(RandomFishArray array, float level)
		{
			if (!Config.Enabled.Value || array == null || array.Length == 0)
			{
				return null;
			}
			if (!IsAvailable)
			{
				return null;
			}
			List<FishData> list = new List<FishData>();
			for (int i = 0; i < array.Length; i++)
			{
				FishLoot val = array.drops[i];
				if (!((Object)(object)val?.fish == (Object)null) && IsLootEligibleAtLevel(val, level) && !HasDonatedByGameId(((ItemData)val.fish).id))
				{
					list.Add(val.fish);
				}
			}
			if (list.Count == 0)
			{
				return null;
			}
			float aquariumProgress = GetAquariumProgress();
			if (aquariumProgress < Config.MinimumMuseumProgress.Value * 100f)
			{
				return null;
			}
			float num = Mathf.Min(Config.MuseumProgressBonusPercent.Value * (aquariumProgress / 10f), Config.MaxBonusChancePercent.Value);
			if (Random.Range(0f, 100f) >= num)
			{
				return null;
			}
			return list[Random.Range(0, list.Count)];
		}

		private static bool IsLootEligibleAtLevel(object loot, float level)
		{
			if (loot == null)
			{
				return false;
			}
			EnsureLootLevelMember(loot.GetType());
			object obj = null;
			try
			{
				if (_lootLevelField != null)
				{
					obj = _lootLevelField.GetValue(loot);
				}
				else
				{
					if (!(_lootLevelProperty != null))
					{
						return true;
					}
					obj = _lootLevelProperty.GetValue(loot);
				}
			}
			catch
			{
				return true;
			}
			if (obj == null)
			{
				return true;
			}
			try
			{
				float num = Convert.ToSingle(obj);
				return level + 0.001f >= num;
			}
			catch
			{
				return true;
			}
		}

		private static void EnsureLootLevelMember(Type lootType)
		{
			if (_lootLevelResolved || lootType == null)
			{
				return;
			}
			_lootLevelResolved = true;
			string[] array = new string[5] { "useLevel", "level", "minLevel", "requiredLevel", "fishingLevel" };
			foreach (string name in array)
			{
				_lootLevelField = lootType.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (_lootLevelField != null)
				{
					return;
				}
				_lootLevelProperty = lootType.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (_lootLevelProperty != null)
				{
					return;
				}
			}
			if (!_lootLevelLoggedMissing)
			{
				_lootLevelLoggedMissing = true;
				ManualLogSource log = Plugin.Log;
				if (log != null)
				{
					log.LogDebug((object)("[TrinketFortune] No level gate on " + lootType.Name + "; fish bias uses full drop list."));
				}
			}
		}
	}
	[BepInPlugin("com.azraelgodking.trinketfortune", "Trinket Fortune", "2.1.3")]
	public class Plugin : BaseUnityPlugin
	{
		public static class PluginInfo
		{
			public const string PLUGIN_GUID = "com.azraelgodking.trinketfortune";

			public const string PLUGIN_NAME = "Trinket Fortune";

			public const string PLUGIN_VERSION = "2.1.3";
		}

		private Harmony _harmony;

		private bool _applicationQuitting;

		public static ManualLogSource Log { get; private set; }

		private void Awake()
		{
			//IL_0035: Unknown result type (might be due to invalid IL or missing references)
			//IL_003f: Expected O, but got Unknown
			Log = ((BaseUnityPlugin)this).Logger;
			ConfigFile val = CreateNamedConfig();
			ConfigFileHelper.ReplacePluginConfig((BaseUnityPlugin)(object)this, val, (Action<string>)Log.LogWarning);
			Config.Bind(val);
			_harmony = new Harmony("com.azraelgodking.trinketfortune");
			try
			{
				FishingTrinketPatches.ApplyPatches(_harmony);
			}
			catch (Exception arg)
			{
				Log.LogError((object)$"Harmony patches failed (game version drift?): {arg}");
			}
			Log.LogInfo((object)"Trinket Fortune v2.1.3 loaded. Fishing loot bias active when S.M.U.T. is installed.");
			ModDiagnostics.LogModStartup(Log, "com.azraelgodking.trinketfortune", "Trinket Fortune", "2.1.3", ModHealthIntegrationSummary.Build(("DevTools", "com.azraelgodking.havendevtools"), ("SMUT", "com.azraelgodking.sunhavenmuseumutilitytracker")), "startup", false);
		}

		private void OnApplicationQuit()
		{
			_applicationQuitting = true;
		}

		private void OnDestroy()
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			Scene activeScene = SceneManager.GetActiveScene();
			string text = ((Scene)(ref activeScene)).name ?? string.Empty;
			string text2 = text.ToLowerInvariant();
			if (_applicationQuitting || !Application.isPlaying || text2.Contains("menu") || text2.Contains("title"))
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogInfo((object)("[Lifecycle] Plugin OnDestroy during expected teardown (scene: " + text + ")"));
				}
			}
			else
			{
				ManualLogSource log2 = Log;
				if (log2 != null)
				{
					log2.LogWarning((object)("[Lifecycle] Plugin OnDestroy outside expected teardown (scene: " + text + ")"));
				}
			}
			Harmony harmony = _harmony;
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
		}

		private static ConfigFile CreateNamedConfig()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Expected O, but got Unknown
			string text = Path.Combine(Paths.ConfigPath, "TrinketFortune.cfg");
			string text2 = Path.Combine(Paths.ConfigPath, "com.azraelgodking.trinketfortune.cfg");
			try
			{
				if (!File.Exists(text) && File.Exists(text2))
				{
					File.Copy(text2, text);
				}
			}
			catch (Exception ex)
			{
				ManualLogSource log = Log;
				if (log != null)
				{
					log.LogWarning((object)("[Config] Migration to TrinketFortune.cfg failed: " + ex.Message));
				}
			}
			return new ConfigFile(text, true);
		}

		public static string GetDevToolsSummary()
		{
			if (Config.Enabled == null)
			{
				return "Not ready";
			}
			bool flag = Chainloader.PluginInfos != null && Chainloader.PluginInfos.ContainsKey("com.azraelgodking.sunhavenmuseumutilitytracker");
			string text = (DonationHelper.IsAvailable ? "S.M.U.T. donations linked" : (flag ? "S.M.U.T. installed (load a save for donation data)" : "standalone mode"));
			if (!Config.Enabled.Value)
			{
				return "Disabled in config | " + text;
			}
			float aquariumProgressPercent = DonationHelper.GetAquariumProgressPercent();
			return $"Aquarium: {aquariumProgressPercent:F1}% | Bonus {Config.MuseumProgressBonusPercent.Value}% per 10% | " + $"Min {Config.MinimumMuseumProgress.Value:P0} | Cap {Config.MaxBonusChancePercent.Value}% | {text}";
		}
	}
}
namespace TrinketFortune.Patches
{
	public static class FishingTrinketPatches
	{
		public static void ApplyPatches(Harmony harmony)
		{
			bool num = TryPatchUtilitiesRandomItem(harmony);
			TryPatchRandomFishArray(harmony);
			if (!num)
			{
				TryPatchFishingRodMuseumCallSites(harmony);
			}
		}

		private static bool TryPatchUtilitiesRandomItem(Harmony harmony)
		{
			//IL_00c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cc: Expected O, but got Unknown
			//IL_0045: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Expected O, but got Unknown
			List<MethodInfo> list = FindUtilitiesRandomItemIntMethods();
			if (list.Count == 0)
			{
				Plugin.Log.LogWarning((object)"Could not find Utilities.RandomItem<int> for museum item bias (game update?). Will try FishingRod call-site fallbacks.");
				return false;
			}
			Exception ex = null;
			foreach (MethodInfo item in list)
			{
				try
				{
					HarmonyMethod val = new HarmonyMethod(typeof(FishingTrinketPatches), "RandomItemInt_Prefix", (Type[])null);
					harmony.Patch((MethodBase)item, val, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Plugin.Log.LogInfo((object)("Patched " + DescribeMethod(item) + " for fishing museum items"));
					return true;
				}
				catch (Exception ex2)
				{
					ex = ex2;
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogDebug((object)("Prefix patch failed for " + DescribeMethod(item) + ": " + ex2.Message));
					}
				}
				try
				{
					HarmonyMethod val2 = new HarmonyMethod(typeof(FishingTrinketPatches), "RandomItemInt_Postfix", (Type[])null);
					harmony.Patch((MethodBase)item, (HarmonyMethod)null, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Plugin.Log.LogInfo((object)("Patched " + DescribeMethod(item) + " (postfix) for fishing museum items"));
					return true;
				}
				catch (Exception ex3)
				{
					ex = ex3;
					ManualLogSource log2 = Plugin.Log;
					if (log2 != null)
					{
						log2.LogDebug((object)("Postfix patch failed for " + DescribeMethod(item) + ": " + ex3.Message));
					}
				}
			}
			Plugin.Log.LogError((object)("Failed to patch Utilities.RandomItem<int>: " + ex?.Message));
			return false;
		}

		private static List<MethodInfo> FindUtilitiesRandomItemIntMethods()
		{
			List<MethodInfo> list = new List<MethodInfo>();
			Type type = null;
			try
			{
				type = typeof(Utilities);
			}
			catch
			{
				type = AccessTools.TypeByName("Wish.Utilities");
			}
			if (type == null)
			{
				return list;
			}
			MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo == null)
				{
					continue;
				}
				string text = methodInfo.Name ?? string.Empty;
				if (!text.Equals("RandomItem", StringComparison.Ordinal) && !text.Equals("GetRandomItem", StringComparison.Ordinal) && !text.Equals("PickRandom", StringComparison.Ordinal) && !text.EndsWith("RandomItem", StringComparison.Ordinal))
				{
					continue;
				}
				MethodInfo methodInfo2 = null;
				try
				{
					if (methodInfo.IsGenericMethodDefinition)
					{
						ParameterInfo[] parameters = methodInfo.GetParameters();
						if (parameters.Length < 1 || parameters.Length > 2)
						{
							continue;
						}
						Type parameterType = parameters[0].ParameterType;
						if (!parameterType.IsGenericType)
						{
							continue;
						}
						Type genericTypeDefinition = parameterType.GetGenericTypeDefinition();
						if (genericTypeDefinition != typeof(IList<>) && genericTypeDefinition != typeof(List<>) && genericTypeDefinition != typeof(IEnumerable<>))
						{
							continue;
						}
						methodInfo2 = methodInfo.MakeGenericMethod(typeof(int));
					}
					else if (methodInfo.IsGenericMethod)
					{
						methodInfo2 = methodInfo;
					}
					else
					{
						ParameterInfo[] parameters2 = methodInfo.GetParameters();
						if (parameters2.Length >= 1 && parameters2[0].ParameterType == typeof(IList<int>) && methodInfo.ReturnType == typeof(int))
						{
							methodInfo2 = methodInfo;
						}
					}
				}
				catch (Exception ex)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogDebug((object)("RandomItem close failed for " + text + ": " + ex.Message));
					}
				}
				if (methodInfo2 != null && !list.Contains(methodInfo2))
				{
					list.Add(methodInfo2);
				}
			}
			return list;
		}

		private static void TryPatchRandomFishArray(Harmony harmony)
		{
			//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
			//IL_0104: Expected O, but got Unknown
			MethodInfo methodInfo = null;
			try
			{
				methodInfo = typeof(RandomFishArray).GetMethod("RandomItem", BindingFlags.Instance | BindingFlags.Public, null, new Type[1] { typeof(float) }, null);
			}
			catch
			{
			}
			if (methodInfo == null)
			{
				foreach (MethodInfo declaredMethod in AccessTools.GetDeclaredMethods(AccessTools.TypeByName("Wish.RandomFishArray") ?? typeof(RandomFishArray)))
				{
					if (!(declaredMethod == null) && declaredMethod.Name.Contains("RandomItem"))
					{
						ParameterInfo[] parameters = declaredMethod.GetParameters();
						if (parameters.Length == 1 && parameters[0].ParameterType == typeof(float))
						{
							methodInfo = declaredMethod;
							break;
						}
					}
				}
			}
			if (methodInfo == null)
			{
				Plugin.Log.LogWarning((object)"Could not find RandomFishArray.RandomItem");
				return;
			}
			try
			{
				harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(FishingTrinketPatches), "RandomFishArray_RandomItem_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				Plugin.Log.LogInfo((object)("Patched " + DescribeMethod(methodInfo) + " for fish bias"));
			}
			catch (Exception ex)
			{
				Plugin.Log.LogError((object)("Failed to patch RandomFishArray.RandomItem: " + ex.Message));
			}
		}

		private static void TryPatchFishingRodMuseumCallSites(Harmony harmony)
		{
			//IL_00c7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			Type type;
			try
			{
				type = typeof(FishingRod);
			}
			catch
			{
				type = AccessTools.TypeByName("Wish.FishingRod");
			}
			if (type == null)
			{
				return;
			}
			int num = 0;
			MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo == null || methodInfo.IsSpecialName || methodInfo.ReturnType != typeof(int))
				{
					continue;
				}
				string text = methodInfo.Name ?? string.Empty;
				if (text.IndexOf("Museum", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("Trinket", StringComparison.OrdinalIgnoreCase) < 0 && text.IndexOf("Bonus", StringComparison.OrdinalIgnoreCase) < 0)
				{
					continue;
				}
				try
				{
					harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(FishingTrinketPatches), "FishingRodInt_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					Plugin.Log.LogInfo((object)("Patched FishingRod." + methodInfo.Name + " as museum-bias fallback"));
					num++;
				}
				catch (Exception ex)
				{
					ManualLogSource log = Plugin.Log;
					if (log != null)
					{
						log.LogDebug((object)("FishingRod." + methodInfo.Name + " fallback patch failed: " + ex.Message));
					}
				}
			}
			if (num == 0)
			{
				ManualLogSource log2 = Plugin.Log;
				if (log2 != null)
				{
					log2.LogWarning((object)"No FishingRod museum call-site fallbacks patched.");
				}
			}
		}

		private static bool RandomItemInt_Prefix(IList<int> list, ref int __result)
		{
			return !TryBiasMuseumList(list, ref __result);
		}

		private static void RandomItemInt_Postfix(IList<int> list, ref int __result)
		{
			TryBiasMuseumList(list, ref __result);
		}

		private static void FishingRodInt_Postfix(ref int __result)
		{
			if (!Config.Enabled.Value)
			{
				return;
			}
			List<int> fishingMuseumItems = FishingRod.fishingMuseumItems;
			if (fishingMuseumItems != null && fishingMuseumItems.Count != 0 && fishingMuseumItems.Contains(__result))
			{
				int num = DonationHelper.PickBiasedFishingMuseumItem();
				if (num != 0)
				{
					__result = num;
				}
			}
		}

		private static bool TryBiasMuseumList(IList<int> list, ref int __result)
		{
			if (!Config.Enabled.Value)
			{
				return false;
			}
			if (list == null || list != FishingRod.fishingMuseumItems)
			{
				return false;
			}
			int num = DonationHelper.PickBiasedFishingMuseumItem();
			if (num == 0)
			{
				return false;
			}
			__result = num;
			return true;
		}

		private static void RandomFishArray_RandomItem_Postfix(RandomFishArray __instance, float level, ref FishData __result)
		{
			FishData val = DonationHelper.PickBiasedFish(__instance, level);
			if ((Object)(object)val != (Object)null)
			{
				__result = val;
			}
		}

		private static string DescribeMethod(MethodInfo mi)
		{
			if (mi == null)
			{
				return "(null)";
			}
			try
			{
				return mi.DeclaringType?.FullName + "." + mi.ToString();
			}
			catch
			{
				return mi.Name;
			}
		}
	}
}