Decompiled source of Cooking Bell Timer v0.3.12

BepInEx/plugins/CookingBellTimer/CookingBellTimer.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Networking;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: AssemblyCompany("CookingBellTimer")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("0.3.12.0")]
[assembly: AssemblyInformationalVersion("0.3.12")]
[assembly: AssemblyProduct("CookingBellTimer")]
[assembly: AssemblyTitle("CookingBellTimer")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyVersion("0.3.12.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 CookingBellTimer
{
	internal static class BellAudio
	{
		internal static AudioClip? Bell;

		private static AudioSource? _source;

		private static bool _paused;

		private static bool _playedForCurrentItem;

		internal static bool PlayedForCurrentItem => _playedForCurrentItem;

		internal static void Initialize(MonoBehaviour host)
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_000a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			GameObject val = new GameObject("CookingBellTimer_Audio");
			Object.DontDestroyOnLoad((Object)val);
			_source = val.AddComponent<AudioSource>();
			_source.spatialBlend = 0f;
			_source.dopplerLevel = 0f;
			_source.bypassReverbZones = true;
			_source.playOnAwake = false;
			_source.loop = false;
			host.StartCoroutine(LoadBell());
		}

		private static IEnumerator LoadBell()
		{
			string text = Path.Combine(Path.GetDirectoryName(typeof(Plugin).Assembly.Location), "sounds", "ding.ogg");
			if (!File.Exists(text))
			{
				Plugin.Log.LogError((object)("Missing bell sound: " + text));
				yield break;
			}
			UnityWebRequest req = UnityWebRequestMultimedia.GetAudioClip(new Uri(text).AbsoluteUri, (AudioType)14);
			try
			{
				yield return req.SendWebRequest();
				if ((int)req.result != 1)
				{
					Plugin.Log.LogError((object)("Failed loading bell: " + req.error));
					yield break;
				}
				Bell = DownloadHandlerAudioClip.GetContent(req);
				Plugin.Log.LogInfo((object)$"Loaded bell ({Bell.length:0.00}s)");
			}
			finally
			{
				((IDisposable)req)?.Dispose();
			}
		}

		internal static void PlayOnce()
		{
			if ((Object)(object)_source != (Object)null && (Object)(object)Bell != (Object)null && !_playedForCurrentItem)
			{
				_source.Stop();
				_source.clip = Bell;
				_source.loop = false;
				_source.volume = Plugin.BellVolume.Value;
				_source.time = 0f;
				_source.Play();
				_paused = false;
				_playedForCurrentItem = true;
				Plugin.Log.LogDebug((object)"Bell triggered.");
			}
		}

		internal static void Pause()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			if (!((Object)_source == (Object)null) && _source.isPlaying)
			{
				_source.Pause();
				_paused = true;
			}
		}

		internal static void Resume()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			if (!((Object)_source == (Object)null) && _paused)
			{
				_source.UnPause();
				_paused = false;
			}
		}

		internal static void Tick()
		{
		}

		internal static void ResetForNewItem()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			if ((Object)_source != (Object)null)
			{
				_source.Stop();
				_source.clip = null;
			}
			_paused = false;
			_playedForCurrentItem = false;
		}

		internal static void StopForBurnt()
		{
			//IL_0005: Unknown result type (might be due to invalid IL or missing references)
			//IL_0010: Expected O, but got Unknown
			if ((Object)_source != (Object)null)
			{
				_source.Stop();
			}
			_paused = false;
		}
	}
	internal static class CookingHook
	{
		public static void Postfix(object __instance, float prev, float next, bool asServer)
		{
			try
			{
				if (!(next <= prev) && RuntimeTargets.WasCookedByLocalPlayer(__instance))
				{
					CookingTracker.Track(__instance);
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Cooking hook failed: " + ex.Message));
			}
		}
	}
	internal static class CookingOverlay
	{
		private const float MinCook = 1f;

		private const float MaxCook = 1.5f;

		private const float Marker = 1.45f;

		private static float _displayMultiplier = 1f;

		private static float _burnProgress;

		private static float _lastUpdate = -999f;

		private static bool _visible;

		private static bool _burning;

		private static Texture2D? _pixel;

		private static GUIStyle? _titleStyle;

		private static GUIStyle? _markerStyle;

		private static GUIStyle? _burningStyle;

		internal static void Initialize()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_000c: Expected O, but got Unknown
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Unknown result type (might be due to invalid IL or missing references)
			//IL_002c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0033: Unknown result type (might be due to invalid IL or missing references)
			//IL_003b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0057: Expected O, but got Unknown
			//IL_0057: Unknown result type (might be due to invalid IL or missing references)
			//IL_005c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_006b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Unknown result type (might be due to invalid IL or missing references)
			//IL_0078: Unknown result type (might be due to invalid IL or missing references)
			//IL_0087: Expected O, but got Unknown
			//IL_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_008c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0093: Unknown result type (might be due to invalid IL or missing references)
			//IL_009b: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00bc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cb: Expected O, but got Unknown
			_pixel = new Texture2D(1, 1);
			_pixel.SetPixel(0, 0, Color.white);
			_pixel.Apply();
			GUIStyle val = new GUIStyle
			{
				alignment = (TextAnchor)4,
				fontSize = 20,
				fontStyle = (FontStyle)1
			};
			val.normal.textColor = Color.white;
			_titleStyle = val;
			GUIStyle val2 = new GUIStyle
			{
				alignment = (TextAnchor)1,
				fontSize = 12,
				fontStyle = (FontStyle)1
			};
			val2.normal.textColor = Color.white;
			_markerStyle = val2;
			GUIStyle val3 = new GUIStyle
			{
				alignment = (TextAnchor)4,
				fontSize = 22,
				fontStyle = (FontStyle)1
			};
			val3.normal.textColor = new Color(1f, 0.86f, 0.12f, 1f);
			_burningStyle = val3;
		}

		internal static void ReportCook(float displayedMultiplier, bool burning, float burnProgress)
		{
			_displayMultiplier = Mathf.Max(0f, displayedMultiplier);
			_burning = burning;
			_burnProgress = Mathf.Clamp01(burnProgress);
			_lastUpdate = Time.unscaledTime;
			_visible = true;
		}

		internal static void HideImmediately()
		{
			_visible = false;
			_displayMultiplier = 1f;
			_burning = false;
			_burnProgress = 0f;
			_lastUpdate = -999f;
		}

		internal static void Tick()
		{
			if (_visible && Time.unscaledTime - _lastUpdate > Plugin.OverlayHideDelay.Value)
			{
				_visible = false;
			}
		}

		internal static void Draw()
		{
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//IL_001a: Expected O, but got Unknown
			//IL_0092: Unknown result type (might be due to invalid IL or missing references)
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_015a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a9: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c3: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00fb: Unknown result type (might be due to invalid IL or missing references)
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0107: Unknown result type (might be due to invalid IL or missing references)
			//IL_0109: Unknown result type (might be due to invalid IL or missing references)
			//IL_010b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0120: Unknown result type (might be due to invalid IL or missing references)
			if (_visible && !((Object)_pixel == (Object)null) && _titleStyle != null && _markerStyle != null && _burningStyle != null)
			{
				float value = Plugin.OverlayWidth.Value;
				float value2 = Plugin.OverlayHeight.Value;
				float num = ((float)Screen.width - value) * 0.5f;
				float num2 = (float)Screen.height - Plugin.OverlayBottomOffset.Value - value2;
				Rect rect = new Rect(num - 3f, num2 - 3f, value + 6f, value2 + 6f);
				Rect val = default(Rect);
				((Rect)(ref val))..ctor(num, num2, value, value2);
				DrawRect(rect, new Color(0f, 0f, 0f, 0.92f));
				if (_burning)
				{
					Color val2 = new Color(0.34f, 0.16f, 0.055f, 0.98f);
					Color val3 = default(Color);
					((Color)(ref val3))..ctor(0.015f, 0.008f, 0.004f, 0.99f);
					Color color = Color.Lerp(val2, val3, _burnProgress);
					DrawRect(val, color);
					GUI.Label(new Rect(num, num2 - 34f, value, 30f), $"BURNING  {_displayMultiplier:0.00}x", _burningStyle);
				}
				else
				{
					DrawRect(val, new Color(0.08f, 0.08f, 0.08f, 0.94f));
					float num3 = Mathf.InverseLerp(1f, 1.5f, Mathf.Clamp(_displayMultiplier, 1f, 1.5f));
					DrawRect(new Rect(num, num2, value * num3, value2), GetCookingGradient(_displayMultiplier));
					DrawMarker(1.45f, val, "1.45x");
					GUI.Label(new Rect(num, num2 - 32f, value, 28f), $"COOKING  {_displayMultiplier:0.00}x", _titleStyle);
				}
			}
		}

		private static Color GetCookingGradient(float multiplier)
		{
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			//IL_0075: Unknown result type (might be due to invalid IL or missing references)
			//IL_0086: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ac: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ad: Unknown result type (might be due to invalid IL or missing references)
			//IL_00be: Unknown result type (might be due to invalid IL or missing references)
			//IL_0094: Unknown result type (might be due to invalid IL or missing references)
			//IL_0095: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a6: Unknown result type (might be due to invalid IL or missing references)
			Color val = default(Color);
			((Color)(ref val))..ctor(0.18f, 0.82f, 0.28f, 0.98f);
			Color val2 = default(Color);
			((Color)(ref val2))..ctor(1f, 0.9f, 0.12f, 0.98f);
			Color val3 = default(Color);
			((Color)(ref val3))..ctor(1f, 0.52f, 0.08f, 0.98f);
			Color val4 = default(Color);
			((Color)(ref val4))..ctor(0.95f, 0.12f, 0.08f, 0.98f);
			if (multiplier <= 1.25f)
			{
				return Color.Lerp(val, val2, Mathf.InverseLerp(1f, 1.25f, multiplier));
			}
			if (multiplier <= 1.4f)
			{
				return Color.Lerp(val2, val3, Mathf.InverseLerp(1.25f, 1.4f, multiplier));
			}
			return Color.Lerp(val3, val4, Mathf.InverseLerp(1.4f, 1.5f, multiplier));
		}

		private static void DrawMarker(float value, Rect bar, string label)
		{
			//IL_0048: 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_007c: Unknown result type (might be due to invalid IL or missing references)
			float num = Mathf.InverseLerp(1f, 1.5f, value);
			float num2 = ((Rect)(ref bar)).x + ((Rect)(ref bar)).width * num;
			DrawRect(new Rect(num2 - 1.5f, ((Rect)(ref bar)).y - 4f, 3f, ((Rect)(ref bar)).height + 8f), Color.white);
			GUI.Label(new Rect(num2 - 38f, ((Rect)(ref bar)).y + ((Rect)(ref bar)).height + 4f, 76f, 20f), label, _markerStyle);
		}

		private static void DrawRect(Rect rect, Color color)
		{
			//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)
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0011: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Expected O, but got Unknown
			Color color2 = GUI.color;
			GUI.color = color;
			GUI.DrawTexture(rect, (Texture)_pixel);
			GUI.color = color2;
		}
	}
	internal static class CookingTracker
	{
		private static WeakReference? _trackedItem;

		private static CooknessAccessor? _accessor;

		private static DisplayedMultiplierAccessor? _displayAccessor;

		private static object? _currentIdentity;

		private const float RawPerfect = 1f;

		private static float _lastRawCookness = 0f;

		private static float _lastDisplayedMultiplier = 1f;

		private static float _lastCookCallTime = -999f;

		private static bool _sessionActive;

		internal static void Track(object item)
		{
			if (item != null)
			{
				if (_currentIdentity == null || _currentIdentity != item)
				{
					_currentIdentity = item;
					_trackedItem = new WeakReference(item);
					_accessor = CooknessAccessor.Resolve(item.GetType());
					_displayAccessor = DisplayedMultiplierAccessor.Resolve(item.GetType());
					_sessionActive = false;
					_lastRawCookness = 0f;
					_lastDisplayedMultiplier = 1f;
					BellAudio.ResetForNewItem();
				}
				if (_accessor != null)
				{
					_sessionActive = true;
					_lastCookCallTime = Time.unscaledTime;
					float rawCookness = _accessor.Read(item);
					Sample(item, rawCookness);
				}
			}
		}

		internal static void Tick()
		{
			if (_sessionActive && Time.unscaledTime - _lastCookCallTime > 0.3f)
			{
				_sessionActive = false;
				BellAudio.Pause();
			}
			else
			{
				if (!_sessionActive || _trackedItem == null || !_trackedItem.IsAlive || _accessor == null)
				{
					return;
				}
				object target = _trackedItem.Target;
				if (target != null)
				{
					Object val = (Object)((target is Object) ? target : null);
					if (val == null || !(val == (Object)null))
					{
						float rawCookness = _accessor.Read(target);
						Sample(target, rawCookness);
					}
				}
			}
		}

		private static void Sample(object item, float rawCookness)
		{
			rawCookness = Mathf.Max(0f, rawCookness);
			bool flag = rawCookness > 1.0005f;
			float displayedMultiplier = GetDisplayedMultiplier(item, rawCookness, flag);
			if (rawCookness > 5E-05f)
			{
				CookingOverlay.ReportCook(displayedMultiplier, flag, GetBurnProgress(rawCookness));
			}
			if (!flag && !BellAudio.PlayedForCurrentItem && _lastDisplayedMultiplier < Plugin.BellThreshold.Value && displayedMultiplier >= Plugin.BellThreshold.Value)
			{
				BellAudio.PlayOnce();
			}
			else if (BellAudio.PlayedForCurrentItem)
			{
				BellAudio.Resume();
			}
			_lastRawCookness = rawCookness;
			_lastDisplayedMultiplier = displayedMultiplier;
		}

		private static float GetDisplayedMultiplier(object item, float rawCookness, bool burning)
		{
			if (_displayAccessor != null && _displayAccessor.TryRead(item, out var value) && value >= 0f && value <= 2f)
			{
				return value;
			}
			if (!burning)
			{
				return 1f + Mathf.Clamp01(rawCookness) * 0.5f;
			}
			float num = Mathf.Max(0f, rawCookness - 1f);
			return Mathf.Max(0f, 1.5f - num * 0.5f);
		}

		private static float GetBurnProgress(float rawCookness)
		{
			if (rawCookness <= 1f)
			{
				return 0f;
			}
			return Mathf.Clamp01(rawCookness - 1f);
		}
	}
	internal sealed class CooknessAccessor
	{
		internal readonly Type TargetType;

		private readonly PropertyInfo? _cooknessProperty;

		private readonly FieldInfo? _syncField;

		private readonly PropertyInfo? _syncValueProperty;

		private CooknessAccessor(Type type, PropertyInfo property)
		{
			TargetType = type;
			_cooknessProperty = property;
		}

		private CooknessAccessor(Type type, FieldInfo field, PropertyInfo valueProperty)
		{
			TargetType = type;
			_syncField = field;
			_syncValueProperty = valueProperty;
		}

		internal static CooknessAccessor? Resolve(Type type)
		{
			PropertyInfo property = type.GetProperty("Cookness", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null && property.CanRead && IsNumeric(property.PropertyType))
			{
				Plugin.Log.LogInfo((object)("Using exact public cookness property: " + type.Name + ".Cookness"));
				return new CooknessAccessor(type, property);
			}
			FieldInfo field = type.GetField("_cookness", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				PropertyInfo property2 = field.FieldType.GetProperty("Value", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property2 != null && property2.CanRead && IsNumeric(property2.PropertyType))
				{
					Plugin.Log.LogWarning((object)"Public Cookness property missing; falling back to _cookness.Value");
					return new CooknessAccessor(type, field, property2);
				}
			}
			Plugin.Log.LogError((object)("Could not resolve Cookness on " + type.FullName));
			return null;
		}

		internal float Read(object target)
		{
			try
			{
				object obj = null;
				if (_cooknessProperty != null)
				{
					obj = _cooknessProperty.GetValue(target);
				}
				else if (_syncField != null && _syncValueProperty != null)
				{
					object value = _syncField.GetValue(target);
					if (value != null)
					{
						obj = _syncValueProperty.GetValue(value);
					}
				}
				if (obj is float result)
				{
					return result;
				}
				if (obj is double num)
				{
					return (float)num;
				}
				if (obj is int num2)
				{
					return num2;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogWarning((object)("Cookness read failed: " + ex.Message));
			}
			return 1f;
		}

		private static bool IsNumeric(Type type)
		{
			if (!(type == typeof(float)) && !(type == typeof(double)))
			{
				return type == typeof(int);
			}
			return true;
		}
	}
	internal sealed class DisplayedMultiplierAccessor
	{
		internal readonly Type TargetType;

		private readonly PropertyInfo? _property;

		private readonly FieldInfo? _field;

		private readonly MethodInfo? _method;

		private DisplayedMultiplierAccessor(Type type, PropertyInfo property)
		{
			TargetType = type;
			_property = property;
		}

		private DisplayedMultiplierAccessor(Type type, FieldInfo field)
		{
			TargetType = type;
			_field = field;
		}

		private DisplayedMultiplierAccessor(Type type, MethodInfo method)
		{
			TargetType = type;
			_method = method;
		}

		internal static DisplayedMultiplierAccessor? Resolve(Type type)
		{
			string[] array = new string[6] { "CookingMultiplier", "CookMultiplier", "CookedMultiplier", "CookingValueMultiplier", "CookValueMultiplier", "CookWorthMultiplier" };
			foreach (string name in array)
			{
				PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.CanRead && IsNumeric(property.PropertyType))
				{
					Plugin.Log.LogInfo((object)("Using direct displayed cooking multiplier property: " + type.Name + "." + property.Name));
					return new DisplayedMultiplierAccessor(type, property);
				}
				FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (field != null && IsNumeric(field.FieldType))
				{
					Plugin.Log.LogInfo((object)("Using direct displayed cooking multiplier field: " + type.Name + "." + field.Name));
					return new DisplayedMultiplierAccessor(type, field);
				}
			}
			array = new string[3] { "GetCookingMultiplier", "GetCookMultiplier", "GetCookedMultiplier" };
			foreach (string name2 in array)
			{
				MethodInfo method = type.GetMethod(name2, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				if (method != null && IsNumeric(method.ReturnType))
				{
					Plugin.Log.LogInfo((object)("Using direct displayed cooking multiplier method: " + type.Name + "." + method.Name + "()"));
					return new DisplayedMultiplierAccessor(type, method);
				}
			}
			Plugin.Log.LogInfo((object)"No direct displayed cooking multiplier member found; using cookness mapping fallback.");
			return null;
		}

		internal bool TryRead(object target, out float value)
		{
			value = 0f;
			try
			{
				object obj = null;
				if (_property != null)
				{
					obj = _property.GetValue(target);
				}
				else if (_field != null)
				{
					obj = _field.GetValue(target);
				}
				else if (_method != null)
				{
					obj = _method.Invoke(target, null);
				}
				if (obj is float num)
				{
					value = num;
					return true;
				}
				if (obj is double num2)
				{
					value = (float)num2;
					return true;
				}
				if (obj is int num3)
				{
					value = num3;
					return true;
				}
			}
			catch (Exception ex)
			{
				Plugin.Log.LogDebug((object)("Direct multiplier read failed; fallback mapping used: " + ex.Message));
			}
			return false;
		}

		private static bool IsNumeric(Type t)
		{
			if (!(t == typeof(float)) && !(t == typeof(double)))
			{
				return t == typeof(int);
			}
			return true;
		}
	}
	[BepInPlugin("ponyfisher.howtofish.cookingbelltimer", "Cooking Bell Timer", "0.3.12")]
	[BepInProcess("How to Fish.exe")]
	public sealed class Plugin : BaseUnityPlugin
	{
		public const string Guid = "ponyfisher.howtofish.cookingbelltimer";

		public const string Name = "Cooking Bell Timer";

		public const string Version = "0.3.12";

		internal static Plugin Instance;

		internal static ManualLogSource Log;

		internal static ConfigEntry<float> BellThreshold;

		internal static ConfigEntry<float> BellVolume;

		internal static ConfigEntry<bool> OverlayEnabled;

		internal static ConfigEntry<float> OverlayWidth;

		internal static ConfigEntry<float> OverlayHeight;

		internal static ConfigEntry<float> OverlayBottomOffset;

		internal static ConfigEntry<float> OverlayHideDelay;

		private Harmony _harmony;

		private void Awake()
		{
			//IL_005e: Unknown result type (might be due to invalid IL or missing references)
			//IL_006d: Expected O, but got Unknown
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			//IL_0072: Expected O, but got Unknown
			//IL_00c0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00cf: Expected O, but got Unknown
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d4: Expected O, but got Unknown
			//IL_0102: Unknown result type (might be due to invalid IL or missing references)
			//IL_0111: Expected O, but got Unknown
			//IL_010c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0116: Expected O, but got Unknown
			//IL_0144: Unknown result type (might be due to invalid IL or missing references)
			//IL_0153: Expected O, but got Unknown
			//IL_014e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0158: Expected O, but got Unknown
			//IL_0186: Unknown result type (might be due to invalid IL or missing references)
			//IL_0195: Expected O, but got Unknown
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			//IL_019a: Expected O, but got Unknown
			//IL_01a0: Unknown result type (might be due to invalid IL or missing references)
			//IL_01aa: Expected O, but got Unknown
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bf: Expected O, but got Unknown
			//IL_01e6: Unknown result type (might be due to invalid IL or missing references)
			//IL_01f3: Expected O, but got Unknown
			Instance = this;
			Log = ((BaseUnityPlugin)this).Logger;
			BellThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("Timing", "BellThreshold", 1.48f, "Displayed cookness multiplier where the bell plays once.");
			BellVolume = ((BaseUnityPlugin)this).Config.Bind<float>("Audio", "BellVolume", 0.27f, new ConfigDescription("Bell volume. Default is 0.27, which is 30% of the previous 0.90 playback level.", (AcceptableValueBase)new AcceptableValueRange<float>(0f, 1f), Array.Empty<object>()));
			OverlayEnabled = ((BaseUnityPlugin)this).Config.Bind<bool>("Overlay", "Enabled", true, "Show the horizontal cooking progress bar.");
			OverlayWidth = ((BaseUnityPlugin)this).Config.Bind<float>("Overlay", "Width", 560f, new ConfigDescription("Cooking bar width in pixels.", (AcceptableValueBase)new AcceptableValueRange<float>(280f, 1100f), Array.Empty<object>()));
			OverlayHeight = ((BaseUnityPlugin)this).Config.Bind<float>("Overlay", "Height", 32f, new ConfigDescription("Cooking bar height in pixels.", (AcceptableValueBase)new AcceptableValueRange<float>(16f, 70f), Array.Empty<object>()));
			OverlayBottomOffset = ((BaseUnityPlugin)this).Config.Bind<float>("Overlay", "BottomOffset", 235f, new ConfigDescription("Distance from bottom of screen.", (AcceptableValueBase)new AcceptableValueRange<float>(30f, 600f), Array.Empty<object>()));
			OverlayHideDelay = ((BaseUnityPlugin)this).Config.Bind<float>("Overlay", "HideDelay", 0.9f, new ConfigDescription("Seconds before the bar hides after cooking stops.", (AcceptableValueBase)new AcceptableValueRange<float>(0.2f, 4f), Array.Empty<object>()));
			BellAudio.Initialize((MonoBehaviour)this);
			CookingOverlay.Initialize();
			_harmony = new Harmony("ponyfisher.howtofish.cookingbelltimer");
			MethodInfo methodInfo = RuntimeTargets.ResolveCooknessChangedMethod();
			if (methodInfo != null)
			{
				_harmony.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(CookingHook), "Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				((BaseUnityPlugin)this).Logger.LogInfo((object)("Patched synchronized cooking update: " + methodInfo.DeclaringType?.FullName + "." + methodInfo.Name));
			}
			else
			{
				((BaseUnityPlugin)this).Logger.LogError((object)"Could not find Item.OnCooknessChange.");
			}
			((BaseUnityPlugin)this).Logger.LogInfo((object)"Cooking Bell Timer 0.3.12 loaded.");
		}

		private void Update()
		{
			CookingTracker.Tick();
			CookingOverlay.Tick();
			BellAudio.Tick();
		}

		private void OnGUI()
		{
			if (OverlayEnabled.Value)
			{
				CookingOverlay.Draw();
			}
		}

		private void OnDestroy()
		{
			try
			{
				Harmony harmony = _harmony;
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
			}
			catch
			{
			}
		}
	}
	internal static class RuntimeTargets
	{
		internal static Type? ItemType;

		private static PropertyInfo? _lastHolderProperty;

		private static PropertyInfo? _localPlayerProperty;

		private static FieldInfo? _localPlayerField;

		internal static MethodInfo? ResolveCooknessChangedMethod()
		{
			ItemType = AccessTools.TypeByName("Item");
			if (ItemType == null)
			{
				return null;
			}
			_lastHolderProperty = AccessTools.Property(ItemType, "LastHolder");
			Type type = AccessTools.TypeByName("Player");
			if (type != null)
			{
				_localPlayerProperty = type.GetProperty("LocalPlayer", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
				_localPlayerField = type.GetField("LocalPlayer", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			}
			if (_lastHolderProperty == null)
			{
				Plugin.Log.LogError((object)"Could not resolve Item.LastHolder.");
			}
			if (_localPlayerProperty == null && _localPlayerField == null)
			{
				Plugin.Log.LogError((object)"Could not resolve Player.LocalPlayer.");
			}
			else
			{
				Plugin.Log.LogInfo((object)"Resolved local player identity for per-player cooking timers.");
			}
			return AccessTools.Method(ItemType, "OnCooknessChange", new Type[3]
			{
				typeof(float),
				typeof(float),
				typeof(bool)
			}, (Type[])null);
		}

		internal static bool WasCookedByLocalPlayer(object item)
		{
			if (item == null || _lastHolderProperty == null || (_localPlayerProperty == null && _localPlayerField == null))
			{
				return false;
			}
			object value = _lastHolderProperty.GetValue(item);
			object obj = _localPlayerProperty?.GetValue(null) ?? _localPlayerField?.GetValue(null);
			if (value != null && obj != null)
			{
				return value == obj;
			}
			return false;
		}
	}
}