Decompiled source of Full Belly v2.2.2

tony4twentys-Full Belly.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
using BepInEx;
using BepInEx.Configuration;
using BepInEx.Logging;
using HarmonyLib;
using Photon.Pun;
using TMPro;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: AssemblyTitle("Full Belly")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Full Belly")]
[assembly: AssemblyCopyright("Copyright ©  2025")]
[assembly: AssemblyTrademark("")]
[assembly: ComVisible(false)]
[assembly: Guid("940386f2-efcb-440c-a8e5-aa2361ab032b")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")]
[assembly: AssemblyVersion("1.0.0.0")]
namespace FullBellyMod;

[BepInPlugin("tony4twentys.full_belly", "Full Belly", "2.2.2")]
[BepInProcess("PEAK.exe")]
public class FullBellyPlugin : BaseUnityPlugin
{
	private static ConfigEntry<float> cfgFullnessDuration;

	private static ConfigEntry<float> cfgAccumulationWindow;

	private static ConfigEntry<float> cfgFullnessThreshold;

	private static ConfigEntry<string> cfgIgnoredItems;

	private static ConfigEntry<bool> cfgShowFullnessTimer;

	internal static ConfigEntry<int> cfgTimerFontSize;

	internal static ConfigEntry<int> cfgPopupFontSize;

	internal static ConfigEntry<float> cfgTimerPosX;

	internal static ConfigEntry<float> cfgTimerPosY;

	internal static ConfigEntry<float> cfgPopupPosX;

	internal static ConfigEntry<float> cfgPopupPosY;

	internal static ConfigEntry<string> cfgTimerColor;

	internal static ConfigEntry<string> cfgPopupColor;

	internal static ConfigEntry<float> cfgPopupSeconds;

	private void Awake()
	{
		//IL_0243: Unknown result type (might be due to invalid IL or missing references)
		//IL_0249: Expected O, but got Unknown
		cfgFullnessDuration = ((BaseUnityPlugin)this).Config.Bind<float>("Full Belly", "FullnessDuration", 300f, "Duration in seconds that hunger is paused after reaching fullness.");
		cfgAccumulationWindow = ((BaseUnityPlugin)this).Config.Bind<float>("Full Belly", "AccumulationWindow", 120f, "Time window in seconds to accumulate small hunger restorations.");
		cfgFullnessThreshold = ((BaseUnityPlugin)this).Config.Bind<float>("Full Belly", "FullnessThreshold", 0.25f, "Total hunger restoration percentage needed to trigger fullness.");
		cfgIgnoredItems = ((BaseUnityPlugin)this).Config.Bind<string>("Full Belly", "IgnoredItems", "", "Comma-separated list of item names to ignore when calculating fullness.Apple Berry Green,Apple Berry Red,Apple Berry Yellow,Airplane Food,Berrynana Blue,Berrynana Brown,Berrynana Pink,Berrynana Yellow,Clusterberry Black,Clusterberry Red,Clusterberry Yellow,Cure-All,Egg,Granola Bar,Item_Coconut_half,Item_Honeycomb,Kingberry Green,Kingberry Purple,Kingberry Yellow,Lollipop,Marshmallow,MedicinalRoot,Mushroom Chubby,Mushroom Cluster Poison,Mushroom Cluster,Mushroom Glow,Mushroom Lace Poison,Mushroom Lace,Mushroom Normie Poison,Mushroom Normie,Napberry,PandorasBox,Pepper Berry,ScoutCookies,TrailMix,Winterberry Orange,Winterberry Yellow,Glizzy.");
		cfgShowFullnessTimer = ((BaseUnityPlugin)this).Config.Bind<bool>("Full Belly", "ShowFullnessTimer", true, "Display countdown timer for fullness expiration.");
		cfgTimerFontSize = ((BaseUnityPlugin)this).Config.Bind<int>("Full Belly", "TimerFontSize", 30, "Font size for the 'Belly Full' countdown text.");
		cfgPopupFontSize = ((BaseUnityPlugin)this).Config.Bind<int>("Full Belly", "PopupFontSize", 30, "Font size for the end popup text.");
		cfgTimerPosX = ((BaseUnityPlugin)this).Config.Bind<float>("Full Belly", "TimerPosX", -450f, "Anchored X position for the timer text (center anchor).");
		cfgTimerPosY = ((BaseUnityPlugin)this).Config.Bind<float>("Full Belly", "TimerPosY", -400f, "Anchored Y position for the timer text (center anchor).");
		cfgPopupPosX = ((BaseUnityPlugin)this).Config.Bind<float>("Full Belly", "PopupPosX", -450f, "Anchored X position for the popup text (center anchor).");
		cfgPopupPosY = ((BaseUnityPlugin)this).Config.Bind<float>("Full Belly", "PopupPosY", -400f, "Anchored Y position for the popup text (center anchor).");
		cfgTimerColor = ((BaseUnityPlugin)this).Config.Bind<string>("Full Belly", "TimerColor", "#00FF00FF", "Timer text color (hex only, #RRGGBB or #RRGGBBAA).");
		cfgPopupColor = ((BaseUnityPlugin)this).Config.Bind<string>("Full Belly", "PopupColor", "#FFFF00FF", "Popup text color (hex only, #RRGGBB or #RRGGBBAA).");
		cfgPopupSeconds = ((BaseUnityPlugin)this).Config.Bind<float>("Full Belly", "PopupSeconds", 3f, "Seconds to display 'Getting hungry again' after the effect ends.");
		((BaseUnityPlugin)this).Logger.LogInfo((object)"Full Belly mod started.");
		FullBellyManager.Initialize(((BaseUnityPlugin)this).Logger, cfgFullnessDuration.Value, cfgAccumulationWindow.Value, cfgFullnessThreshold.Value, cfgIgnoredItems.Value, cfgShowFullnessTimer.Value);
		Harmony val = new Harmony("tony4twentys.full_belly");
		val.PatchAll();
	}
}
public class FullBellyManager : MonoBehaviour
{
	[CompilerGenerated]
	private sealed class <ApplyFullness>d__29 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public CharacterAfflictions afflictions;

		public FullBellyManager <>4__this;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <ApplyFullness>d__29(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0073: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Expected O, but got Unknown
			//IL_00da: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<>4__this.isFull = true;
				afflictions.hungerPerSecond = 0f;
				<>4__this.logger.LogInfo((object)$"Full Belly active for {<>4__this.fullnessDuration} seconds.");
				<>2__current = (object)new WaitForSeconds(<>4__this.fullnessDuration);
				<>1__state = 1;
				return true;
			case 1:
				<>1__state = -1;
				afflictions.hungerPerSecond = <>4__this.cachedHungerRate;
				<>4__this.isFull = false;
				<>4__this.logger.LogInfo((object)"Full Belly expired. Hunger gain restored.");
				<>4__this.ShowPopup("Getting Hungry Again", ParseColor(FullBellyPlugin.cfgPopupColor.Value, Color.yellow));
				return false;
			}
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	[CompilerGenerated]
	private sealed class <FullnessCountdown>d__23 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public float duration;

		public FullBellyManager <>4__this;

		private float <remaining>5__1;

		private int <minutes>5__2;

		private int <seconds>5__3;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <FullnessCountdown>d__23(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f8: Expected O, but got Unknown
			//IL_00d7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00dc: Unknown result type (might be due to invalid IL or missing references)
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				<remaining>5__1 = duration;
				<>4__this.EnsureCanvas();
				<>4__this.EnsureTimerText();
				break;
			case 1:
				<>1__state = -1;
				<remaining>5__1 -= 1f;
				break;
			}
			if (<remaining>5__1 > 0f)
			{
				<minutes>5__2 = Mathf.FloorToInt(<remaining>5__1 / 60f);
				<seconds>5__3 = Mathf.FloorToInt(<remaining>5__1 % 60f);
				if ((Object)(object)<>4__this.timerText != (Object)null)
				{
					((TMP_Text)<>4__this.timerText).text = $"Belly Full: {<minutes>5__2:0}:{<seconds>5__3:00}";
					((Graphic)<>4__this.timerText).color = ParseColor(FullBellyPlugin.cfgTimerColor.Value, Color.green);
				}
				<>2__current = (object)new WaitForSeconds(1f);
				<>1__state = 1;
				return true;
			}
			if ((Object)(object)<>4__this.timerText != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)<>4__this.timerText).gameObject);
				<>4__this.timerText = null;
			}
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	[CompilerGenerated]
	private sealed class <ShowPopupForSeconds>d__32 : IEnumerator<object>, IDisposable, IEnumerator
	{
		private int <>1__state;

		private object <>2__current;

		public string message;

		public Color color;

		public float seconds;

		public FullBellyManager <>4__this;

		private float <t>5__1;

		object IEnumerator<object>.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		object IEnumerator.Current
		{
			[DebuggerHidden]
			get
			{
				return <>2__current;
			}
		}

		[DebuggerHidden]
		public <ShowPopupForSeconds>d__32(int <>1__state)
		{
			this.<>1__state = <>1__state;
		}

		[DebuggerHidden]
		void IDisposable.Dispose()
		{
			<>1__state = -2;
		}

		private bool MoveNext()
		{
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			switch (<>1__state)
			{
			default:
				return false;
			case 0:
				<>1__state = -1;
				if (!<>4__this.showFullnessTimer)
				{
					return false;
				}
				<>4__this.EnsureCanvas();
				<>4__this.EnsurePopupText();
				if ((Object)(object)<>4__this.popupText != (Object)null)
				{
					((TMP_Text)<>4__this.popupText).text = message;
					((Graphic)<>4__this.popupText).color = color;
				}
				<t>5__1 = 0f;
				break;
			case 1:
				<>1__state = -1;
				break;
			}
			if (<t>5__1 < seconds)
			{
				if ((Object)(object)<>4__this.popupText == (Object)null)
				{
					return false;
				}
				<t>5__1 += Time.deltaTime;
				<>2__current = null;
				<>1__state = 1;
				return true;
			}
			if ((Object)(object)<>4__this.popupText != (Object)null)
			{
				Object.Destroy((Object)(object)((Component)<>4__this.popupText).gameObject);
				<>4__this.popupText = null;
			}
			return false;
		}

		bool IEnumerator.MoveNext()
		{
			//ILSpy generated this explicit interface implementation from .override directive in MoveNext
			return this.MoveNext();
		}

		[DebuggerHidden]
		void IEnumerator.Reset()
		{
			throw new NotSupportedException();
		}
	}

	private static GameObject managerObject;

	private static FullBellyManager instance;

	private ManualLogSource logger;

	private float hungerRestoreAccumulator;

	private float timeSinceLastRestore;

	private float accumulationWindow;

	private float fullnessThreshold;

	private float fullnessDuration;

	private Coroutine fullnessCoroutine;

	private Coroutine timerCoroutine;

	private bool isFull;

	private bool hasLoggedReset;

	private float cachedHungerRate = -1f;

	private bool showFullnessTimer;

	private readonly Queue<(string itemName, float value)> restoreIntents = new Queue<(string, float)>();

	private HashSet<string> ignoredItems = new HashSet<string>();

	private TextMeshProUGUI timerText;

	private TextMeshProUGUI popupText;

	private bool wasDead;

	public static void Initialize(ManualLogSource log, float duration, float window, float threshold, string ignoredItemsCSV, bool showTimer)
	{
		//IL_0020: Unknown result type (might be due to invalid IL or missing references)
		//IL_002a: Expected O, but got Unknown
		if ((Object)(object)managerObject != (Object)null)
		{
			Object.Destroy((Object)(object)managerObject);
		}
		managerObject = new GameObject("FullBellyManager");
		Object.DontDestroyOnLoad((Object)(object)managerObject);
		instance = managerObject.AddComponent<FullBellyManager>();
		instance.logger = log;
		instance.fullnessDuration = duration;
		instance.accumulationWindow = window;
		instance.fullnessThreshold = threshold;
		instance.showFullnessTimer = showTimer;
		instance.ignoredItems = new HashSet<string>(from s in ignoredItemsCSV.Split(new char[1] { ',' })
			select s.Trim() into s
			where !string.IsNullOrEmpty(s)
			select s, StringComparer.OrdinalIgnoreCase);
		SceneManager.activeSceneChanged += instance.OnSceneChanged;
	}

	public static void HandleHungerRestore(string itemName, float value)
	{
		if ((Object)(object)instance == (Object)null || string.IsNullOrEmpty(itemName))
		{
			return;
		}
		if ((Object)(object)Character.localCharacter?.data != (Object)null && Character.localCharacter.data.dead)
		{
			instance.logger.LogInfo((object)"[Full Belly] Ignored hunger while dead.");
			return;
		}
		string text = itemName.Replace("(Clone)", string.Empty).Trim();
		if (text.Contains(":"))
		{
			text = text.Split(new char[1] { ':' }).Last();
		}
		if (instance.ignoredItems.Contains(text.ToLowerInvariant()))
		{
			instance.logger.LogInfo((object)("[Full Belly] Ignored hunger from '" + text + "'."));
		}
		else
		{
			instance.restoreIntents.Enqueue((text, value));
		}
	}

	private void OnSceneChanged(Scene oldScene, Scene newScene)
	{
		logger.LogInfo((object)"Scene changed. Resetting Full Belly state.");
		ResetFullBelly("Scene changed");
		try
		{
			float num = 0.0005f * Ascents.hungerRateMultiplier;
			if (num > 0f)
			{
				cachedHungerRate = num;
				logger.LogInfo((object)$"[Scene Init] Cached base hungerPerSecond: {num}");
			}
			else
			{
				logger.LogWarning((object)"[Scene Init] Hunger rate multiplier returned zero or negative. Skipping cache.");
			}
		}
		catch (Exception ex)
		{
			logger.LogWarning((object)("[Scene Init] Could not determine hunger rate: " + ex.Message));
		}
	}

	private void ResetFullBelly(string reason)
	{
		if (fullnessCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(fullnessCoroutine);
			fullnessCoroutine = null;
		}
		if (timerCoroutine != null)
		{
			((MonoBehaviour)this).StopCoroutine(timerCoroutine);
			timerCoroutine = null;
		}
		if ((Object)(object)timerText != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)timerText).gameObject);
			timerText = null;
		}
		if ((Object)(object)popupText != (Object)null)
		{
			Object.Destroy((Object)(object)((Component)popupText).gameObject);
			popupText = null;
		}
		CharacterAfflictions val = Character.localCharacter?.refs?.afflictions;
		if ((Object)(object)val != (Object)null)
		{
			float hungerPerSecond = ((cachedHungerRate > 0f) ? cachedHungerRate : (0.0005f * Ascents.hungerRateMultiplier));
			val.hungerPerSecond = hungerPerSecond;
		}
		isFull = false;
		hungerRestoreAccumulator = 0f;
		timeSinceLastRestore = 0f;
		hasLoggedReset = false;
		restoreIntents.Clear();
		ManualLogSource obj = logger;
		if (obj != null)
		{
			obj.LogInfo((object)("[Full Belly] Reset: " + reason));
		}
	}

	[IteratorStateMachine(typeof(<FullnessCountdown>d__23))]
	private IEnumerator FullnessCountdown(float duration)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <FullnessCountdown>d__23(0)
		{
			<>4__this = this,
			duration = duration
		};
	}

	private void CreateOrUpdatePersistentTimer()
	{
		if (showFullnessTimer)
		{
			EnsureCanvas();
			EnsureTimerText();
		}
	}

	private void EnsureCanvas()
	{
		//IL_0029: Unknown result type (might be due to invalid IL or missing references)
		//IL_002f: Expected O, but got Unknown
		//IL_0064: Unknown result type (might be due to invalid IL or missing references)
		GameObject obj = GameObject.Find("FullBellyNotificationCanvas");
		Canvas val = ((obj != null) ? obj.GetComponent<Canvas>() : null);
		if ((Object)(object)val == (Object)null)
		{
			GameObject val2 = new GameObject("FullBellyNotificationCanvas");
			val = val2.AddComponent<Canvas>();
			val.renderMode = (RenderMode)0;
			val.sortingOrder = 999;
			CanvasScaler val3 = val2.AddComponent<CanvasScaler>();
			val3.uiScaleMode = (ScaleMode)1;
			val3.referenceResolution = new Vector2(1920f, 1080f);
			val3.screenMatchMode = (ScreenMatchMode)0;
			val3.matchWidthOrHeight = 0.5f;
			val2.AddComponent<GraphicRaycaster>();
			Object.DontDestroyOnLoad((Object)(object)val2);
		}
	}

	private void EnsureTimerText()
	{
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Expected O, but got Unknown
		GameObject obj = GameObject.Find("FullBellyNotificationCanvas");
		Canvas val = ((obj != null) ? obj.GetComponent<Canvas>() : null);
		if (!((Object)(object)val == (Object)null))
		{
			if ((Object)(object)timerText == (Object)null)
			{
				GameObject val2 = new GameObject("FullBellyTimerText");
				val2.transform.SetParent(((Component)val).transform);
				timerText = val2.AddComponent<TextMeshProUGUI>();
				((Graphic)timerText).raycastTarget = false;
				((TMP_Text)timerText).enableWordWrapping = false;
				((TMP_Text)timerText).alignment = (TextAlignmentOptions)514;
				((TMP_Text)timerText).fontStyle = (FontStyles)1;
			}
			RectTransform component = ((Component)timerText).GetComponent<RectTransform>();
			component.sizeDelta = new Vector2(800f, 120f);
			component.anchorMin = new Vector2(0.5f, 0.5f);
			component.anchorMax = new Vector2(0.5f, 0.5f);
			component.pivot = new Vector2(0.5f, 0.5f);
			component.anchoredPosition = new Vector2(FullBellyPlugin.cfgTimerPosX.Value, FullBellyPlugin.cfgTimerPosY.Value);
			((TMP_Text)timerText).fontSize = Mathf.Clamp(FullBellyPlugin.cfgTimerFontSize.Value, 10, 96);
		}
	}

	private void EnsurePopupText()
	{
		//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00cb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
		//IL_00f7: Unknown result type (might be due to invalid IL or missing references)
		//IL_0117: Unknown result type (might be due to invalid IL or missing references)
		//IL_003e: Unknown result type (might be due to invalid IL or missing references)
		//IL_0045: Expected O, but got Unknown
		GameObject obj = GameObject.Find("FullBellyNotificationCanvas");
		Canvas val = ((obj != null) ? obj.GetComponent<Canvas>() : null);
		if (!((Object)(object)val == (Object)null))
		{
			if ((Object)(object)popupText == (Object)null)
			{
				GameObject val2 = new GameObject("FullBellyPopupText");
				val2.transform.SetParent(((Component)val).transform);
				popupText = val2.AddComponent<TextMeshProUGUI>();
				((Graphic)popupText).raycastTarget = false;
				((TMP_Text)popupText).enableWordWrapping = false;
				((TMP_Text)popupText).alignment = (TextAlignmentOptions)514;
				((TMP_Text)popupText).fontStyle = (FontStyles)1;
			}
			RectTransform component = ((Component)popupText).GetComponent<RectTransform>();
			component.sizeDelta = new Vector2(800f, 120f);
			component.anchorMin = new Vector2(0.5f, 0.5f);
			component.anchorMax = new Vector2(0.5f, 0.5f);
			component.pivot = new Vector2(0.5f, 0.5f);
			component.anchoredPosition = new Vector2(FullBellyPlugin.cfgPopupPosX.Value, FullBellyPlugin.cfgPopupPosY.Value);
			((TMP_Text)popupText).fontSize = Mathf.Clamp(FullBellyPlugin.cfgPopupFontSize.Value, 10, 96);
		}
	}

	private void LateUpdate()
	{
		timeSinceLastRestore += Time.deltaTime;
		Character localCharacter = Character.localCharacter;
		if ((Object)(object)localCharacter == (Object)null || localCharacter.refs == null || (Object)(object)localCharacter.refs.afflictions == (Object)null)
		{
			return;
		}
		CharacterData data = localCharacter.data;
		if ((Object)(object)data != (Object)null)
		{
			if (data.dead && !wasDead)
			{
				ResetFullBelly("Player died");
				wasDead = true;
			}
			else if (!data.dead && wasDead)
			{
				ResetFullBelly("Player revived");
				wasDead = false;
			}
		}
		if (!isFull && localCharacter.refs.afflictions.hungerPerSecond <= 0f && cachedHungerRate > 0f)
		{
			localCharacter.refs.afflictions.hungerPerSecond = cachedHungerRate;
			logger.LogWarning((object)$"[Fallback Reset] hungerPerSecond was 0 while not full. Restored to cached value: {cachedHungerRate}");
		}
		while (restoreIntents.Count > 0)
		{
			var (arg, num) = restoreIntents.Dequeue();
			logger.LogInfo((object)$"Applying hunger from: {arg}, value: {num * 100f:0.00}%");
			if (num >= fullnessThreshold || hungerRestoreAccumulator + num >= fullnessThreshold)
			{
				logger.LogInfo((object)"Fullness triggered.");
				if (fullnessCoroutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(fullnessCoroutine);
				}
				if (timerCoroutine != null)
				{
					((MonoBehaviour)this).StopCoroutine(timerCoroutine);
				}
				fullnessCoroutine = ((MonoBehaviour)this).StartCoroutine(ApplyFullness(localCharacter.refs.afflictions));
				if (showFullnessTimer)
				{
					timerCoroutine = ((MonoBehaviour)this).StartCoroutine(FullnessCountdown(fullnessDuration));
				}
				hungerRestoreAccumulator = 0f;
				timeSinceLastRestore = 0f;
				hasLoggedReset = false;
			}
			else
			{
				hungerRestoreAccumulator += num;
				timeSinceLastRestore = 0f;
				hasLoggedReset = false;
				logger.LogInfo((object)$"Accumulated: {num * 100f:0.00}%, Total: {hungerRestoreAccumulator * 100f:0.00}%");
			}
		}
		if (timeSinceLastRestore >= accumulationWindow && !hasLoggedReset)
		{
			logger.LogInfo((object)"Accumulation window expired. Resetting.");
			hungerRestoreAccumulator = 0f;
			hasLoggedReset = true;
		}
	}

	[IteratorStateMachine(typeof(<ApplyFullness>d__29))]
	private IEnumerator ApplyFullness(CharacterAfflictions afflictions)
	{
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <ApplyFullness>d__29(0)
		{
			<>4__this = this,
			afflictions = afflictions
		};
	}

	private static Color ParseColor(string s, Color fallback)
	{
		//IL_00eb: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
		//IL_000c: Unknown result type (might be due to invalid IL or missing references)
		//IL_000d: Unknown result type (might be due to invalid IL or missing references)
		//IL_00ef: Unknown result type (might be due to invalid IL or missing references)
		//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
		//IL_00da: Unknown result type (might be due to invalid IL or missing references)
		//IL_00df: Unknown result type (might be due to invalid IL or missing references)
		try
		{
			if (string.IsNullOrWhiteSpace(s))
			{
				return fallback;
			}
			s = s.Trim();
			if (s.StartsWith("#"))
			{
				string text = s.Substring(1);
				byte b = byte.MaxValue;
				byte b2 = byte.MaxValue;
				byte b3 = byte.MaxValue;
				byte b4 = byte.MaxValue;
				if (text.Length == 6 || text.Length == 8)
				{
					b = byte.Parse(text.Substring(0, 2), NumberStyles.HexNumber);
					b2 = byte.Parse(text.Substring(2, 2), NumberStyles.HexNumber);
					b3 = byte.Parse(text.Substring(4, 2), NumberStyles.HexNumber);
					if (text.Length == 8)
					{
						b4 = byte.Parse(text.Substring(6, 2), NumberStyles.HexNumber);
					}
					return Color32.op_Implicit(new Color32(b, b2, b3, b4));
				}
			}
		}
		catch
		{
		}
		return fallback;
	}

	private void ShowPopup(string message, Color color)
	{
		//IL_0013: Unknown result type (might be due to invalid IL or missing references)
		if (showFullnessTimer)
		{
			((MonoBehaviour)this).StartCoroutine(ShowPopupForSeconds(message, color, Mathf.Max(0.5f, FullBellyPlugin.cfgPopupSeconds.Value)));
		}
	}

	[IteratorStateMachine(typeof(<ShowPopupForSeconds>d__32))]
	private IEnumerator ShowPopupForSeconds(string message, Color color, float seconds)
	{
		//IL_0015: Unknown result type (might be due to invalid IL or missing references)
		//IL_0016: Unknown result type (might be due to invalid IL or missing references)
		//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
		return new <ShowPopupForSeconds>d__32(0)
		{
			<>4__this = this,
			message = message,
			color = color,
			seconds = seconds
		};
	}
}
[HarmonyPatch(typeof(Item))]
[HarmonyPatch(/*Could not decode attribute arguments.*/)]
public class Patch_FinishCastPrimary
{
	public static MethodBase TargetMethod()
	{
		return typeof(Item).GetMethod("FinishCastPrimary", BindingFlags.Instance | BindingFlags.NonPublic);
	}

	public static void Postfix(Item __instance)
	{
		if ((Object)(object)__instance == (Object)null)
		{
			return;
		}
		Character localCharacter = Character.localCharacter;
		if ((Object)(object)__instance.holderCharacter != (Object)(object)localCharacter)
		{
			return;
		}
		ItemAction[] components = ((Component)__instance).GetComponents<ItemAction>();
		ItemAction[] array = components;
		foreach (ItemAction val in array)
		{
			if (!(((object)val).GetType().Name == "Action_RestoreHunger"))
			{
				continue;
			}
			FieldInfo field = ((object)val).GetType().GetField("restorationAmount", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(field == null))
			{
				float num = (float)field.GetValue(val);
				if (num > 0f)
				{
					FullBellyManager.HandleHungerRestore(((Object)__instance).name, num);
				}
			}
		}
	}
}
[HarmonyPatch(typeof(Character), "GetFedItemRPC")]
public class Patch_GetFedItemRPC
{
	public static void Postfix(Character __instance, int itemPhotonID)
	{
		bool? obj;
		if (__instance == null)
		{
			obj = null;
		}
		else
		{
			PhotonView photonView = ((MonoBehaviourPun)__instance).photonView;
			obj = ((photonView != null) ? new bool?(!photonView.IsMine) : null);
		}
		bool? flag = obj;
		if (flag.GetValueOrDefault(true))
		{
			return;
		}
		PhotonView val = PhotonView.Find(itemPhotonID);
		if ((Object)(object)val == (Object)null)
		{
			return;
		}
		Item component = ((Component)val).GetComponent<Item>();
		if ((Object)(object)component == (Object)null)
		{
			return;
		}
		ItemAction[] components = ((Component)component).GetComponents<ItemAction>();
		ItemAction[] array = components;
		foreach (ItemAction val2 in array)
		{
			if (!(((object)val2).GetType().Name == "Action_RestoreHunger"))
			{
				continue;
			}
			FieldInfo field = ((object)val2).GetType().GetField("restorationAmount", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (!(field == null))
			{
				float num = (float)field.GetValue(val2);
				if (num > 0f)
				{
					FullBellyManager.HandleHungerRestore(((Object)component).name + " (Fed)", num);
				}
			}
		}
	}
}