Decompiled source of ReliableCooking v0.1.2

BepInEx/plugins/ReliableCooking/ReliableCooking.dll

Decompiled a week ago
using System;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.CompilerServices;
using BepInEx;
using BepInEx.Configuration;
using HarmonyLib;
using ReliableStationSafety;
using UnityEngine;

[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: CompilationRelaxations(8)]
[assembly: AssemblyMetadata("AI_Assisted_Creation", "Coded with the assistance of ChatGPT 6.0; packaged with OpenAI Codex.")]
[assembly: AssemblyMetadata("AI_Model_Vendor", "OpenAI")]
[assembly: AssemblyVersion("0.0.0.0")]
namespace ReliableCooking
{
	[BepInIncompatibility("aedenthorn.CookingStationTweaks")]
	[BepInPlugin("au.tyvalheim.reliablecooking", "Reliable Cooking", "0.1.2")]
	public sealed class Plugin : BaseUnityPlugin
	{
		[HarmonyPatch(typeof(CookingStation), "CookItem")]
		internal static class InputPatch
		{
			[HarmonyPriority(0)]
			private static bool Prefix(CookingStation __instance, Humanoid __0, ItemData __1, ref bool __result, bool __runOriginal, out FoodAttempt __state)
			{
				__state = null;
				if (!__runOriginal)
				{
					return false;
				}
				Plugin instance = Instance;
				Player val = (Player)(object)((__0 is Player) ? __0 : null);
				if ((Object)(object)instance == (Object)null || !instance.Enabled.Value || (Object)(object)val == (Object)null || (Object)(object)val != (Object)(object)Player.m_localPlayer || (!Rules.Food(((Object)__instance).name) && !(((Object)__instance).name.Replace("(Clone)", "").Trim() == "piece_FrostFoundry")))
				{
					return true;
				}
				__result = false;
				ZNetView component = ((Component)__instance).GetComponent<ZNetView>();
				if (instance.inputFaulted)
				{
					instance.InputMessage(val, "Inputs paused after an error; restart before retrying. No new input consumed.");
					return false;
				}
				try
				{
					if (Rules.Food(((Object)__instance).name) && (Object)(object)component != (Object)null && component.IsValid() && component.HasOwner() && !component.IsOwner())
					{
						string message;
						bool result = RemoteFoodInput.Begin(__instance, val, __1, out __state, out message);
						if (message != null)
						{
							instance.InputMessage(val, message);
						}
						return result;
					}
					if (!CanWrite(__instance, component, val))
					{
						instance.InputMessage(val, "Station is remote-owned, loading or protected. Food kept in your inventory; cooking settings apply when this client owns it.");
						return false;
					}
					if (__1 == null || !Object.op_Implicit((Object)(object)__1.m_dropPrefab))
					{
						return false;
					}
					foreach (ItemMessage incompatibleItem in __instance.m_incompatibleItems)
					{
						if (Object.op_Implicit((Object)(object)incompatibleItem.m_item) && incompatibleItem.m_item.m_itemData.m_shared.m_name == __1.m_shared.m_name)
						{
							return true;
						}
					}
					if (!(bool)AllowedInput.Invoke(__instance, new object[1] { __1 }))
					{
						return true;
					}
					int num = (int)FreeSlot.Invoke(__instance, null);
					Inventory inventory = ((Humanoid)val).GetInventory();
					if (num < 0 || !inventory.ContainsItem(__1) || __1.m_stack <= 0)
					{
						return false;
					}
					ZDO zDO = component.GetZDO();
					string text = "slot" + num;
					if (zDO.GetString(text, "") != "" || !CanWrite(__instance, component, val))
					{
						return false;
					}
					List<ItemData> allItems = inventory.GetAllItems();
					int val2 = allItems.IndexOf(__1);
					int stack = __1.m_stack;
					__1.m_stack--;
					if (__1.m_stack == 0)
					{
						allItems.Remove(__1);
					}
					try
					{
						if (!CanWrite(__instance, component, val))
						{
							throw new InvalidOperationException("Ownership changed before station input.");
						}
						AddInput.Invoke(__instance, new object[3]
						{
							ZDOMan.GetSessionID(),
							((Object)__1.m_dropPrefab).name,
							__1.m_cheated
						});
						if (zDO.GetString(text, "") == "")
						{
							throw new InvalidOperationException("Station did not accept its input.");
						}
					}
					catch
					{
						if (zDO.GetString(text, "") == "")
						{
							__1.m_stack = stack;
							if (!allItems.Contains(__1))
							{
								allItems.Insert(Math.Min(val2, allItems.Count), __1);
							}
						}
						InventoryChanged.Invoke(inventory, new object[2] { false, false });
						throw;
					}
					InventoryChanged.Invoke(inventory, new object[2] { false, false });
					__result = true;
				}
				catch (Exception ex)
				{
					instance.inputFaulted = true;
					((BaseUnityPlugin)instance).Logger.LogError((object)("Station inputs paused until restart after error; inspect inventory and station before retrying. " + ex));
				}
				return false;
			}

			private static Exception Finalizer(Exception __exception, FoodAttempt __state)
			{
				RemoteFoodInput.Finish(__state);
				return __exception;
			}
		}

		[HarmonyPatch(typeof(CookingStation), "Awake")]
		internal static class SetupPatch
		{
			[HarmonyPriority(800)]
			private static void Prefix(CookingStation __instance)
			{
				Plugin instance = Instance;
				if ((Object)(object)instance == (Object)null || !instance.Enabled.Value)
				{
					return;
				}
				try
				{
					Configure(__instance, instance.SlotMultiplier.Value, instance.CookTimeMultiplier.Value, instance.CastTimeMultiplier.Value, instance.PreventBurning.Value);
				}
				catch (Exception ex)
				{
					((Component)__instance).gameObject.AddComponent<ConfigurationFailed>();
					((BaseUnityPlugin)instance).Logger.LogError((object)("Station customization skipped; original station arrays retained and native initialization continues. Station=" + ((Object)__instance).name + "; " + ex));
				}
			}
		}

		[HarmonyPatch(typeof(CookingStation), "UpdateCooking")]
		internal static class CompletePatch
		{
			private static void Postfix(CookingStation __instance, ZNetView ___m_nview)
			{
				//IL_01a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b8: Unknown result type (might be due to invalid IL or missing references)
				Plugin instance = Instance;
				if ((Object)(object)instance == (Object)null || instance.outputFaulted || !instance.Enabled.Value || (Object)(object)((Component)__instance).GetComponent<ConfigurationFailed>() != (Object)null || !Object.op_Implicit((Object)(object)___m_nview) || !___m_nview.IsValid() || !___m_nview.IsOwner())
				{
					return;
				}
				bool flag = Rules.Food(((Object)__instance).name);
				bool flag2 = ((Object)__instance).name.Replace("(Clone)", "").Trim() == "piece_FrostFoundry";
				if (((!flag || !instance.AutoPop.Value) && (!flag2 || !instance.AutoPopCasts.Value)) || (__instance.m_recordCrafter && (!Object.op_Implicit((Object)(object)Player.m_localPlayer) || ((Character)Player.m_localPlayer).IsDead())))
				{
					return;
				}
				try
				{
					for (int i = 0; i < __instance.m_slots.Length; i++)
					{
						if (!(bool)Done.Invoke(__instance, null))
						{
							break;
						}
						if (!___m_nview.IsValid())
						{
							break;
						}
						if (!___m_nview.IsOwner())
						{
							break;
						}
						ZDO zDO = ___m_nview.GetZDO();
						int num = -1;
						for (int j = 0; j < __instance.m_slots.Length; j++)
						{
							string text = zDO.GetString("slot" + j, "");
							if (text != "" && (bool)ItemDone.Invoke(__instance, new object[1] { text }))
							{
								num = j;
								break;
							}
						}
						if (num >= 0 && ___m_nview.IsValid() && ___m_nview.IsOwner())
						{
							Remove.Invoke(__instance, new object[3]
							{
								0L,
								((Component)__instance).transform.position + ((Component)__instance).transform.forward,
								1
							});
							if (zDO.GetString("slot" + num, "") != "")
							{
								throw new InvalidOperationException("Native output did not clear the completed slot; automatic output will not retry.");
							}
							continue;
						}
						break;
					}
				}
				catch (Exception ex)
				{
					instance.outputFaulted = true;
					((BaseUnityPlugin)instance).Logger.LogError((object)("Automatic output paused until restart after exception; inspect station before retrying. Configuration was not changed. " + ex));
				}
			}
		}

		public const string Id = "au.tyvalheim.reliablecooking";

		public const string Version = "0.1.2";

		private bool inputFaulted;

		private float nextInputMessage;

		private static readonly MethodInfo AddInput = AccessTools.Method(typeof(CookingStation), "RPC_AddItem", (Type[])null, (Type[])null);

		private static readonly MethodInfo FreeSlot = AccessTools.Method(typeof(CookingStation), "GetFreeSlot", (Type[])null, (Type[])null);

		private static readonly MethodInfo AllowedInput = AccessTools.Method(typeof(CookingStation), "IsItemAllowed", new Type[1] { typeof(ItemData) }, (Type[])null);

		private static readonly MethodInfo InventoryChanged = AccessTools.Method(typeof(Inventory), "Changed", new Type[2]
		{
			typeof(bool),
			typeof(bool)
		}, (Type[])null);

		internal static Plugin Instance;

		internal ConfigEntry<bool> Enabled;

		internal ConfigEntry<bool> PreventBurning;

		internal ConfigEntry<bool> AutoPop;

		internal ConfigEntry<bool> AutoPopCasts;

		internal ConfigEntry<float> SlotMultiplier;

		internal ConfigEntry<float> CookTimeMultiplier;

		internal ConfigEntry<float> CastTimeMultiplier;

		private Harmony harmony;

		private bool outputFaulted;

		private static readonly MethodInfo Done = AccessTools.Method(typeof(CookingStation), "HaveDoneItem", (Type[])null, (Type[])null);

		private static readonly MethodInfo ItemDone = AccessTools.Method(typeof(CookingStation), "IsItemDone", (Type[])null, (Type[])null);

		private static readonly MethodInfo Remove = AccessTools.Method(typeof(CookingStation), "RPC_RemoveDoneItem", (Type[])null, (Type[])null);

		private void InputMessage(Player player, string message)
		{
			if (!(Time.unscaledTime < nextInputMessage))
			{
				nextInputMessage = Time.unscaledTime + 1.5f;
				((BaseUnityPlugin)this).Logger.LogInfo((object)("[Input] " + message));
				((Character)player).Message((MessageType)1, "Reliable Cooking: " + message, 0, (Sprite)null, false);
			}
		}

		private static bool CanWrite(CookingStation station, ZNetView view, Player player)
		{
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)view != (Object)null && view.IsValid() && view.IsOwner() && !((Character)player).IsDead() && !((Character)player).IsTeleporting())
			{
				return PrivateArea.CheckAccess(((Component)station).transform.position, 0f, false, true);
			}
			return false;
		}

		private void Awake()
		{
			//IL_0099: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a3: Expected O, but got Unknown
			//IL_00d8: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Expected O, but got Unknown
			//IL_0117: Unknown result type (might be due to invalid IL or missing references)
			//IL_0121: Expected O, but got Unknown
			//IL_01b3: Unknown result type (might be due to invalid IL or missing references)
			//IL_01bd: Expected O, but got Unknown
			Instance = this;
			Enabled = ((BaseUnityPlugin)this).Config.Bind<bool>("General", "Enabled", true, "Enable at startup. Restart after changes; empty extra cooking slots before reducing capacity/removing the mod.");
			PreventBurning = ((BaseUnityPlugin)this).Config.Bind<bool>("Food", "PreventBurning", true, "Keep cooked food from burning on supported food stations.");
			AutoPop = ((BaseUnityPlugin)this).Config.Bind<bool>("Food", "AutoPop", true, "Drop all completed food beside locally owned stations in the same update using Valheim's native output handler.");
			SlotMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Food", "SlotMultiplier", 1f, new ConfigDescription("Default keeps vanilla capacity for mixed-mod groups. Opt-in extra food slots require matching settings on every potential owner, including server. Never resize the Frost Foundry. Empty extra slots before reducing; restart required.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(1f, 8f), new object[0]));
			CookTimeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Food", "CookTimeMultiplier", 1f, new ConfigDescription("Food cooking-time multiplier. Restart required.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 10f), new object[0]));
			CastTimeMultiplier = ((BaseUnityPlugin)this).Config.Bind<float>("Foundry", "CastTimeMultiplier", 1f, new ConfigDescription("Frost Foundry processing-time multiplier. 1 preserves native timing and fuel cost; changing time changes fuel consumed. Restart required.", (AcceptableValueBase)(object)new AcceptableValueRange<float>(0.05f, 10f), new object[0]));
			AutoPopCasts = ((BaseUnityPlugin)this).Config.Bind<bool>("Foundry", "AutoPopCasts", false, "Opt in to dropping completed casts beside the locally owned foundry. Requires a living local player for native crafter attribution. Default leaves gear on the foundry.");
			try
			{
				if (Done == null || Remove == null || ItemDone == null || AddInput == null || FreeSlot == null || AllowedInput == null || InventoryChanged == null)
				{
					throw new MissingMethodException("CookingStation output API unavailable");
				}
				harmony = new Harmony("au.tyvalheim.reliablecooking");
				harmony.PatchAll();
				((BaseUnityPlugin)this).Logger.LogInfo((object)"Reliable Cooking 0.1.2 loaded. Food slots are expandable; Frost Foundry keeps its native slot and switches. Inspired by aedenthorn's Cooking Station Tweaks.");
			}
			catch (Exception ex)
			{
				if (harmony != null)
				{
					harmony.UnpatchSelf();
				}
				((BaseUnityPlugin)this).Logger.LogError((object)ex);
			}
		}

		private void OnDestroy()
		{
			if (harmony != null)
			{
				harmony.UnpatchSelf();
			}
			if ((Object)(object)Instance == (Object)(object)this)
			{
				Instance = null;
			}
		}

		internal static void Configure(CookingStation station, float slots, float foodTime, float castTime, bool noBurn)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Expected O, but got Unknown
			//IL_01b5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01c5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01cc: Unknown result type (might be due to invalid IL or missing references)
			if ((Object)(object)((Component)station).GetComponent<Configured>() != (Object)null)
			{
				return;
			}
			bool flag = Rules.Food(((Object)station).name);
			bool flag2 = ((Object)station).name.Replace("(Clone)", "").Trim() == "piece_FrostFoundry";
			if (!flag && !flag2)
			{
				return;
			}
			List<ItemConversion> list = new List<ItemConversion>();
			foreach (ItemConversion item in station.m_conversion)
			{
				ItemConversion val = new ItemConversion();
				val.m_from = item.m_from;
				val.m_to = item.m_to;
				val.m_cookTime = Rules.Duration(item.m_cookTime, flag ? foodTime : castTime);
				list.Add(val);
			}
			int num = ((station.m_slots != null) ? station.m_slots.Length : 0);
			int num2 = Rules.Slots(num, slots, flag && !station.m_recordCrafter && !station.m_moveObjectWhileCooking);
			Transform[] slots2 = station.m_slots;
			ParticleSystem[] donePS = station.m_donePS;
			ParticleSystem[] burntPS = station.m_burntPS;
			List<GameObject> list2 = new List<GameObject>();
			try
			{
				if (num2 > num)
				{
					Transform[] array = (Transform[])(object)new Transform[num2];
					Array.Copy(station.m_slots, array, num);
					for (int i = num; i < num2; i++)
					{
						Transform val2 = station.m_slots[(i - num) % num];
						Transform transform = Object.Instantiate<GameObject>(((Component)val2).gameObject, val2.parent, false).transform;
						list2.Add(((Component)transform).gameObject);
						((Object)transform).name = "ReliableCooking_slot_" + i;
						float num3 = ((float)(i - num) + 1f) / ((float)(num2 - num) + 1f);
						transform.position = Vector3.Lerp(station.m_slots[0].position, station.m_slots[num - 1].position, num3);
						array[i] = transform;
					}
					slots2 = array;
					donePS = Expand(station.m_donePS, array, list2);
					burntPS = Expand(station.m_burntPS, array, list2);
				}
				((Component)station).gameObject.AddComponent<Configured>();
				station.m_slots = slots2;
				station.m_donePS = donePS;
				station.m_burntPS = burntPS;
				station.m_conversion = list;
				if (flag && noBurn)
				{
					station.m_canOvercookItems = false;
				}
			}
			catch
			{
				foreach (GameObject item2 in list2)
				{
					if (Object.op_Implicit((Object)(object)item2))
					{
						item2.SetActive(false);
						Object.Destroy((Object)(object)item2);
					}
				}
				throw;
			}
		}

		private static ParticleSystem[] Expand(ParticleSystem[] source, Transform[] slots, List<GameObject> created)
		{
			//IL_0070: Unknown result type (might be due to invalid IL or missing references)
			//IL_007d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0082: Unknown result type (might be due to invalid IL or missing references)
			//IL_008a: Unknown result type (might be due to invalid IL or missing references)
			//IL_008f: Unknown result type (might be due to invalid IL or missing references)
			if (source == null || source.Length == 0)
			{
				return source;
			}
			ParticleSystem[] array = (ParticleSystem[])(object)new ParticleSystem[slots.Length];
			for (int i = 0; i < slots.Length; i++)
			{
				if (i < source.Length)
				{
					array[i] = source[i];
					continue;
				}
				int num = i % source.Length;
				GameObject val = Object.Instantiate<GameObject>(((Component)source[num]).gameObject, ((Component)source[num]).transform.parent, false);
				created.Add(val);
				((Object)val).name = "ReliableCooking_effect_" + i;
				val.transform.position = slots[i].position + ((Component)source[num]).transform.position - slots[num].position;
				array[i] = val.GetComponent<ParticleSystem>();
			}
			return array;
		}
	}
	public sealed class Configured : MonoBehaviour
	{
	}
	public sealed class ConfigurationFailed : MonoBehaviour
	{
	}
	internal static class Rules
	{
		internal static bool Food(string name)
		{
			name = (name ?? "").Replace("(Clone)", "").Trim();
			if (!(name == "piece_cookingstation") && !(name == "piece_cookingstation_iron"))
			{
				return name == "piece_oven";
			}
			return true;
		}

		internal static int Slots(int original, float multiplier, bool food)
		{
			if (!food || original < 2 || float.IsNaN(multiplier) || float.IsInfinity(multiplier))
			{
				return original;
			}
			return Math.Max(original, Math.Min(32, (int)Math.Round((float)original * Math.Max(1f, multiplier))));
		}

		internal static float Duration(float original, float multiplier)
		{
			if (original <= 0f || float.IsNaN(original) || float.IsInfinity(original))
			{
				return original;
			}
			if (float.IsNaN(multiplier) || float.IsInfinity(multiplier))
			{
				return original;
			}
			return Math.Max(1f, original * Math.Max(0.05f, Math.Min(10f, multiplier)));
		}
	}
}
namespace ReliableStationSafety
{
	public sealed class PendingFood : MonoBehaviour
	{
		internal bool Waiting;

		internal string Input;

		internal string Output;

		internal long Owner;

		internal string[] Before;

		internal float Started;

		internal int AcceptedSlot = -1;

		internal void Observe(long sender, int slot, string item)
		{
			if (Waiting && sender == Owner && slot >= 0 && slot < Before.Length)
			{
				if (Before[slot] == "" && (item == Input || item == Output))
				{
					AcceptedSlot = slot;
				}
				if (slot == AcceptedSlot && item == "")
				{
					Waiting = false;
				}
			}
		}

		internal bool Confirmed(ZDO state)
		{
			if (!Waiting)
			{
				return true;
			}
			for (int i = 0; i < Before.Length; i++)
			{
				string text = state.GetString("slot" + i, "");
				if (Before[i] == "" && (text == Input || text == Output))
				{
					Waiting = false;
					return true;
				}
			}
			return false;
		}
	}
	internal sealed class FoodAttempt
	{
		internal PendingFood Pending;

		internal Inventory Inventory;

		internal string Name;

		internal int Count;
	}
	internal static class RemoteFoodInput
	{
		private const string CapacityKey = "reliable_workstations_food_capacity";

		private const string OwnerKey = "reliable_workstations_food_capacity_owner";

		internal static int NativeCapacity(string name)
		{
			name = (name ?? "").Replace("(Clone)", "").Trim();
			return name switch
			{
				"piece_cookingstation" => 2, 
				"piece_cookingstation_iron" => 5, 
				"piece_oven" => 4, 
				_ => 0, 
			};
		}

		internal static void Publish(CookingStation station)
		{
			if (NativeCapacity(((Object)station).name) != 0 && station.m_slots != null)
			{
				ZNetView component = ((Component)station).GetComponent<ZNetView>();
				if (!((Object)(object)component == (Object)null) && component.IsValid() && component.IsOwner())
				{
					ZDO zDO = component.GetZDO();
					zDO.Set("reliable_workstations_food_capacity", station.m_slots.Length);
					zDO.Set("reliable_workstations_food_capacity_owner", zDO.GetOwner());
				}
			}
		}

		internal static void ObserveSnapshot(CookingStation station)
		{
			PendingFood component = ((Component)station).GetComponent<PendingFood>();
			if (!((Object)(object)component == (Object)null) && component.Waiting)
			{
				ZNetView component2 = ((Component)station).GetComponent<ZNetView>();
				if ((Object)(object)component2 != (Object)null && component2.IsValid())
				{
					component.Confirmed(component2.GetZDO());
				}
			}
		}

		internal static bool Begin(CookingStation station, Player player, ItemData item, out FoodAttempt attempt, out string message)
		{
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			attempt = null;
			message = null;
			ZNetView component = ((Component)station).GetComponent<ZNetView>();
			if (item == null || (Object)(object)item.m_dropPrefab == (Object)null || !((Humanoid)player).GetInventory().ContainsItem(item) || item.m_stack <= 0 || (Object)(object)component == (Object)null || !component.IsValid() || !component.HasOwner() || ((Character)player).IsDead() || ((Character)player).IsTeleporting() || !PrivateArea.CheckAccess(((Component)station).transform.position, 0f, false, true))
			{
				return false;
			}
			ZDO zDO = component.GetZDO();
			PendingFood pendingFood = ((Component)station).GetComponent<PendingFood>();
			if ((Object)(object)pendingFood == (Object)null)
			{
				pendingFood = ((Component)station).gameObject.AddComponent<PendingFood>();
			}
			if (!pendingFood.Confirmed(zDO))
			{
				if (Time.unscaledTime - pendingFood.Started > 3f)
				{
					message = "Waiting for the station's previous food input to appear. Remaining food is still in your inventory.";
				}
				return false;
			}
			int num = NativeCapacity(((Object)station).name);
			int num2 = zDO.GetInt("reliable_workstations_food_capacity", 0);
			if (zDO.GetLong("reliable_workstations_food_capacity_owner", 0L) == zDO.GetOwner() && num2 >= num && num2 <= 32)
			{
				num = num2;
			}
			num = Math.Min(num, station.m_slots.Length);
			string[] array = new string[num];
			bool flag = false;
			for (int i = 0; i < num; i++)
			{
				array[i] = zDO.GetString("slot" + i, "");
				if (array[i] == "")
				{
					flag = true;
				}
			}
			if (!flag)
			{
				message = "The station's confirmed cooking slots are full. Remaining food is still in your inventory.";
				return false;
			}
			string text = null;
			foreach (ItemConversion item2 in station.m_conversion)
			{
				if ((Object)(object)item2.m_from != (Object)null && ((Object)item2.m_from).name == ((Object)item.m_dropPrefab).name)
				{
					text = (((Object)(object)item2.m_to != (Object)null) ? ((Object)item2.m_to).name : null);
					break;
				}
			}
			if (text == null)
			{
				return true;
			}
			Inventory inventory = ((Humanoid)player).GetInventory();
			pendingFood.Input = ((Object)item.m_dropPrefab).name;
			pendingFood.Output = text;
			pendingFood.Before = array;
			pendingFood.Owner = zDO.GetOwner();
			pendingFood.Started = Time.unscaledTime;
			pendingFood.AcceptedSlot = -1;
			pendingFood.Waiting = true;
			attempt = new FoodAttempt
			{
				Pending = pendingFood,
				Inventory = inventory,
				Name = item.m_shared.m_name,
				Count = inventory.CountItems(item.m_shared.m_name, -1, true)
			};
			return true;
		}

		internal static void Finish(FoodAttempt attempt)
		{
			if (attempt != null && (Object)(object)attempt.Pending != (Object)null && attempt.Inventory.CountItems(attempt.Name, -1, true) >= attempt.Count)
			{
				attempt.Pending.Waiting = false;
			}
		}
	}
	[HarmonyPatch(typeof(CookingStation), "CookItem")]
	internal static class FoodInputObservation
	{
		[HarmonyPriority(801)]
		private static void Prefix(CookingStation __instance)
		{
			RemoteFoodInput.ObserveSnapshot(__instance);
		}
	}
	[HarmonyPatch(typeof(CookingStation), "RPC_SetSlotVisual")]
	internal static class FoodVisualObservation
	{
		private static void Postfix(CookingStation __instance, long __0, int __1, string __2)
		{
			PendingFood component = ((Component)__instance).GetComponent<PendingFood>();
			if ((Object)(object)component != (Object)null)
			{
				component.Observe(__0, __1, __2);
			}
		}
	}
	[HarmonyPatch(typeof(CookingStation), "UpdateCooking")]
	internal static class FoodCapacityAdvertisement
	{
		private static void Prefix(CookingStation __instance)
		{
			RemoteFoodInput.ObserveSnapshot(__instance);
		}

		private static void Postfix(CookingStation __instance)
		{
			RemoteFoodInput.Publish(__instance);
		}
	}
}