Decompiled source of CookBook v1.2.10

CookBook.dll

Decompiled 3 days ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using BepInEx;
using BepInEx.Bootstrap;
using BepInEx.Configuration;
using BepInEx.Logging;
using CookBook;
using HG;
using Microsoft.CodeAnalysis;
using On.RoR2;
using On.RoR2.UI;
using RiskOfOptions;
using RiskOfOptions.OptionConfigs;
using RiskOfOptions.Options;
using RoR2;
using RoR2.ContentManagement;
using RoR2.Items;
using RoR2.UI;
using TMPro;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.EventSystems;
using UnityEngine.Events;
using UnityEngine.Networking;
using UnityEngine.TextCore;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CookBook")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+237d6957d0f956ad03bba299394a18093e053517")]
[assembly: AssemblyProduct("CookBook")]
[assembly: AssemblyTitle("CookBook")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
internal static class RecipeFilter
{
	public enum RecipeFilterCategory
	{
		All,
		Damage,
		Healing,
		Utility
	}

	public static RecipeFilterCategory CurrentCategory = RecipeFilterCategory.All;

	private static readonly Dictionary<RecipeFilterCategory, ItemTag> CategoryToTag = new Dictionary<RecipeFilterCategory, ItemTag>
	{
		{
			RecipeFilterCategory.Damage,
			(ItemTag)1
		},
		{
			RecipeFilterCategory.Healing,
			(ItemTag)2
		},
		{
			RecipeFilterCategory.Utility,
			(ItemTag)3
		}
	};

	public static void ApplyFiltersToUI(List<CraftUI.RecipeRowUI> rows, string searchTerm)
	{
		if (rows == null)
		{
			return;
		}
		string text = searchTerm?.Trim().ToLowerInvariant();
		foreach (CraftUI.RecipeRowUI row in rows)
		{
			if (!((Object)(object)row.RowGO == (Object)null))
			{
				bool flag = string.IsNullOrEmpty(text) || EntryMatchesSearch(row.Entry, text);
				bool flag2 = EntryMatchesFilter(row.Entry);
				row.RowGO.SetActive(flag && flag2);
			}
		}
	}

	public static void CycleCategory()
	{
		int num = (int)(CurrentCategory + 1);
		if (num > 3)
		{
			num = 0;
		}
		CurrentCategory = (RecipeFilterCategory)num;
	}

	public static string GetLabel()
	{
		return CurrentCategory switch
		{
			RecipeFilterCategory.Damage => "<size=150%><sprite name=\"icon\"></size> DMG", 
			RecipeFilterCategory.Healing => "<size=150%><sprite name=\"icon\"></size> HEAL", 
			RecipeFilterCategory.Utility => "<size=150%><sprite name=\"icon\"></size> UTIL", 
			_ => "ALL", 
		};
	}

	private static bool EntryMatchesFilter(CraftPlanner.CraftableEntry entry)
	{
		//IL_0040: Unknown result type (might be due to invalid IL or missing references)
		if (entry == null)
		{
			return false;
		}
		if (CurrentCategory == RecipeFilterCategory.All)
		{
			return true;
		}
		int resultIndex = entry.ResultIndex;
		if (resultIndex < 0)
		{
			return false;
		}
		if (resultIndex >= ItemCatalog.itemCount)
		{
			return true;
		}
		ItemDef itemDef = ItemCatalog.GetItemDef((ItemIndex)resultIndex);
		if ((Object)(object)itemDef != (Object)null)
		{
			return itemDef.ContainsTag(CategoryToTag[CurrentCategory]);
		}
		return false;
	}

	private static bool EntryMatchesSearch(CraftPlanner.CraftableEntry entry, string term)
	{
		if (string.IsNullOrEmpty(term))
		{
			return true;
		}
		if (entry == null)
		{
			return false;
		}
		string entryDisplayName = CraftUI.GetEntryDisplayName(entry);
		if (!string.IsNullOrEmpty(entryDisplayName))
		{
			return entryDisplayName.IndexOf(term, StringComparison.OrdinalIgnoreCase) >= 0;
		}
		return false;
	}

	public static void PatchVanillaNRE(orig_FilterAvailableOptions orig, CraftingController self)
	{
		NetworkUIPromptController component = ((Component)self).GetComponent<NetworkUIPromptController>();
		if (!((Object)(object)component == (Object)null) && !((Object)(object)component.currentParticipantMaster == (Object)null))
		{
			orig.Invoke(self);
		}
	}
}
namespace CookBook
{
	internal static class ChatNetworkHandler
	{
		[CompilerGenerated]
		private static class <>O
		{
			public static hook_AddMessage_string <0>__OnAddMessage;

			public static hook_OnProcessed <1>__OnUserChatMessageProcessed;
		}

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

			private object <>2__current;

			public NetworkUser target;

			public int idx;

			public int qty;

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

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

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

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

			private bool MoveNext()
			{
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0027: Expected O, but got Unknown
				//IL_0042: Unknown result type (might be due to invalid IL or missing references)
				//IL_0047: Unknown result type (might be due to invalid IL or missing references)
				//IL_0061: Unknown result type (might be due to invalid IL or missing references)
				//IL_0066: Unknown result type (might be due to invalid IL or missing references)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(2f);
					<>1__state = 1;
					return true;
				case 1:
				{
					<>1__state = -1;
					Dictionary<uint, float> pendingAcks = _pendingAcks;
					NetworkInstanceId netId = ((NetworkBehaviour)target).netId;
					if (pendingAcks.ContainsKey(((NetworkInstanceId)(ref netId)).Value))
					{
						Dictionary<uint, float> pendingAcks2 = _pendingAcks;
						netId = ((NetworkBehaviour)target).netId;
						pendingAcks2.Remove(((NetworkInstanceId)(ref netId)).Value);
						DebugLog.Trace(_log, "[Net] No ACK from " + target.userName + ". Falling back to raw text.");
						SendRawTextFallback(target, idx, qty);
					}
					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 const string NetPrefix = "CB_NET:";

		private static ManualLogSource _log;

		private static bool _enabled;

		private static readonly Dictionary<uint, float> _pendingAcks = new Dictionary<uint, float>();

		private const float AckTimeout = 2f;

		internal static event Action<NetworkUser, string, int, int> OnIncomingObjective;

		internal static void Init(ManualLogSource log)
		{
			_log = log;
		}

		internal static void Enable()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			if (!_enabled)
			{
				_enabled = true;
				object obj = <>O.<0>__OnAddMessage;
				if (obj == null)
				{
					hook_AddMessage_string val = OnAddMessage;
					<>O.<0>__OnAddMessage = val;
					obj = (object)val;
				}
				Chat.AddMessage_string += (hook_AddMessage_string)obj;
				object obj2 = <>O.<1>__OnUserChatMessageProcessed;
				if (obj2 == null)
				{
					hook_OnProcessed val2 = OnUserChatMessageProcessed;
					<>O.<1>__OnUserChatMessageProcessed = val2;
					obj2 = (object)val2;
				}
				UserChatMessage.OnProcessed += (hook_OnProcessed)obj2;
			}
		}

		internal static void Disable()
		{
			//IL_001e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0023: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Expected O, but got Unknown
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			//IL_0049: Expected O, but got Unknown
			if (_enabled)
			{
				_enabled = false;
				object obj = <>O.<0>__OnAddMessage;
				if (obj == null)
				{
					hook_AddMessage_string val = OnAddMessage;
					<>O.<0>__OnAddMessage = val;
					obj = (object)val;
				}
				Chat.AddMessage_string -= (hook_AddMessage_string)obj;
				object obj2 = <>O.<1>__OnUserChatMessageProcessed;
				if (obj2 == null)
				{
					hook_OnProcessed val2 = OnUserChatMessageProcessed;
					<>O.<1>__OnUserChatMessageProcessed = val2;
					obj2 = (object)val2;
				}
				UserChatMessage.OnProcessed -= (hook_OnProcessed)obj2;
			}
		}

		private static void OnUserChatMessageProcessed(orig_OnProcessed orig, UserChatMessage self)
		{
			if (self.text == null || !self.text.Contains("CB_NET:"))
			{
				orig.Invoke(self);
			}
		}

		public static void SendObjectiveRequest(NetworkUser target, string command, int unifiedIdx, int quantity)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c9: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ce: Unknown result type (might be due to invalid IL or missing references)
			if (_enabled && !((Object)(object)target == (Object)null))
			{
				LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
				NetworkUser val = ((firstLocalUser != null) ? firstLocalUser.currentNetworkUser : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					object[] obj = new object[6] { "CB_NET:", null, null, null, null, null };
					NetworkInstanceId netId = ((NetworkBehaviour)val).netId;
					obj[1] = ((NetworkInstanceId)(ref netId)).Value;
					netId = ((NetworkBehaviour)target).netId;
					obj[2] = ((NetworkInstanceId)(ref netId)).Value;
					obj[3] = command;
					obj[4] = unifiedIdx;
					obj[5] = quantity;
					string text = string.Format("{0}{1}:{2}:{3}:{4}:{5}", obj);
					DebugLog.Trace(_log, "[Net Out] Sending packet to " + target.userName + ": " + text);
					Console.instance.SubmitCmd(val, "say \"" + text + "\"", false);
					Dictionary<uint, float> pendingAcks = _pendingAcks;
					netId = ((NetworkBehaviour)target).netId;
					pendingAcks[((NetworkInstanceId)(ref netId)).Value] = Time.time;
					((MonoBehaviour)RoR2Application.instance).StopCoroutine("CheckAckTimeout");
					((MonoBehaviour)RoR2Application.instance).StartCoroutine(CheckAckTimeout(target, unifiedIdx, quantity));
				}
			}
		}

		[IteratorStateMachine(typeof(<CheckAckTimeout>d__13))]
		private static IEnumerator CheckAckTimeout(NetworkUser target, int idx, int qty)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CheckAckTimeout>d__13(0)
			{
				target = target,
				idx = idx,
				qty = qty
			};
		}

		private static void SendRawTextFallback(NetworkUser target, int unifiedIdx, int qty)
		{
			//IL_00ec: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f3: Expected O, but got Unknown
			//IL_00b6: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_0066: 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_007d: Unknown result type (might be due to invalid IL or missing references)
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			if (!Object.op_Implicit((Object)(object)((firstLocalUser != null) ? firstLocalUser.currentNetworkUser : null)) || (Object)(object)target == (Object)null)
			{
				return;
			}
			string text = "Unknown Item";
			string text2 = "ffffff";
			if (unifiedIdx < ItemCatalog.itemCount)
			{
				ItemDef itemDef = ItemCatalog.GetItemDef((ItemIndex)unifiedIdx);
				if ((Object)(object)itemDef != (Object)null)
				{
					text = Language.currentLanguage.GetLocalizedStringByToken(itemDef.nameToken);
					ItemTierDef itemTierDef = ItemTierCatalog.GetItemTierDef(itemDef.tier);
					ColorCatalog.GetColor(itemTierDef.colorIndex);
					if ((Object)(object)itemTierDef != (Object)null)
					{
						text2 = ColorCatalog.GetColorHexString(itemTierDef.colorIndex);
					}
				}
			}
			else
			{
				EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef((EquipmentIndex)(unifiedIdx - ItemCatalog.itemCount));
				if ((Object)(object)equipmentDef != (Object)null)
				{
					text = Language.currentLanguage.GetLocalizedStringByToken(equipmentDef.nameToken);
					text2 = ColorCatalog.GetColorHexString(equipmentDef.colorIndex);
				}
			}
			string text3 = $"<color=#d299ff>[CookBook]</color> @{target.userName}, I'm looking for ({qty}) <color=#{text2}>{text}</color>!";
			SimpleChatMessage val = new SimpleChatMessage();
			val.baseToken = "{0}";
			val.paramTokens = new string[1] { text3 };
			Chat.SendBroadcastChat((ChatMessageBase)(object)val);
		}

		private static void SendAck(uint senderID, string originalCmd)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			NetworkUser val = ((firstLocalUser != null) ? firstLocalUser.currentNetworkUser : null);
			object[] obj = new object[4] { "CB_NET:", null, null, null };
			NetworkInstanceId netId = ((NetworkBehaviour)val).netId;
			obj[1] = ((NetworkInstanceId)(ref netId)).Value;
			obj[2] = senderID;
			obj[3] = originalCmd;
			string text = string.Format("{0}{1}:{2}:ACK:{3}:0", obj);
			Console.instance.SubmitCmd(val, "say \"" + text + "\"", false);
		}

		public static void SendGlobalAbort()
		{
			//IL_002e: 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)
			if (_enabled)
			{
				LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
				NetworkUser val = ((firstLocalUser != null) ? firstLocalUser.currentNetworkUser : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					NetworkInstanceId netId = ((NetworkBehaviour)val).netId;
					string text = string.Format("{0}{1}:0:ABORT:0:0", "CB_NET:", ((NetworkInstanceId)(ref netId)).Value);
					DebugLog.Trace(_log, "[Net Out] Sending Global Abort: " + text);
					Console.instance.SubmitCmd(val, "say \"" + text + "\"", false);
				}
			}
		}

		public static void SendObjectiveSuccess(NetworkUser target, int unifiedIdx)
		{
			//IL_0042: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_005d: Unknown result type (might be due to invalid IL or missing references)
			if (_enabled && !((Object)(object)target == (Object)null))
			{
				LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
				NetworkUser val = ((firstLocalUser != null) ? firstLocalUser.currentNetworkUser : null);
				if (Object.op_Implicit((Object)(object)val))
				{
					object[] obj = new object[4] { "CB_NET:", null, null, null };
					NetworkInstanceId netId = ((NetworkBehaviour)val).netId;
					obj[1] = ((NetworkInstanceId)(ref netId)).Value;
					netId = ((NetworkBehaviour)target).netId;
					obj[2] = ((NetworkInstanceId)(ref netId)).Value;
					obj[3] = unifiedIdx;
					string text = string.Format("{0}{1}:{2}:SUCCESS:{3}:0", obj);
					DebugLog.Trace(_log, $"[Net Out] Sending Success signal to {target.userName} for item {unifiedIdx}");
					Console.instance.SubmitCmd(val, "say \"" + text + "\"", false);
				}
			}
		}

		private static void OnAddMessage(orig_AddMessage_string orig, string message)
		{
			if (_enabled && message.Contains("CB_NET:"))
			{
				int num = message.IndexOf("CB_NET:");
				ParseAndProcess(message.Substring(num + "CB_NET:".Length));
			}
			else
			{
				orig.Invoke(message);
			}
		}

		private static void ParseAndProcess(string data)
		{
			//IL_0097: Unknown result type (might be due to invalid IL or missing references)
			//IL_009c: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				string text = data;
				int num = data.IndexOf('<');
				if (num != -1)
				{
					text = data.Substring(0, num);
				}
				string[] array = text.Split(':');
				if (array.Length < 5 || !uint.TryParse(array[0], out var senderID) || !uint.TryParse(array[1], out var result))
				{
					return;
				}
				string text2 = array[2].ToUpper();
				LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
				NetworkUser val = ((firstLocalUser != null) ? firstLocalUser.currentNetworkUser : null);
				if ((Object)(object)val == (Object)null)
				{
					return;
				}
				NetworkInstanceId netId;
				if (text2 == "ACK")
				{
					uint num2 = result;
					netId = ((NetworkBehaviour)val).netId;
					if (num2 == ((NetworkInstanceId)(ref netId)).Value)
					{
						DebugLog.Trace(_log, $"[Net In] ACK received from {senderID}. Request confirmed.");
						_pendingAcks.Remove(senderID);
						return;
					}
				}
				if (result != 0)
				{
					netId = ((NetworkBehaviour)val).netId;
					if (((NetworkInstanceId)(ref netId)).Value != result)
					{
						return;
					}
				}
				if (text2 != "ACK")
				{
					SendAck(senderID, text2);
				}
				int result3;
				int result4;
				if (text2 == "ABORT")
				{
					DebugLog.Trace(_log, $"[Net In] Global Abort received from Sender {senderID}");
					ObjectiveTracker.ClearObjectivesFromSender(senderID);
				}
				else if (text2 == "SUCCESS")
				{
					if (int.TryParse(array[3], out var result2))
					{
						ObjectiveTracker.ClearSpecificRequest(senderID, result2);
					}
				}
				else if (int.TryParse(array[3], out result3) && int.TryParse(array[4], out result4))
				{
					NetworkUser arg = ((IEnumerable<NetworkUser>)NetworkUser.readOnlyInstancesList).FirstOrDefault((Func<NetworkUser, bool>)delegate(NetworkUser u)
					{
						//IL_0001: Unknown result type (might be due to invalid IL or missing references)
						//IL_0006: Unknown result type (might be due to invalid IL or missing references)
						NetworkInstanceId netId2 = ((NetworkBehaviour)u).netId;
						return ((NetworkInstanceId)(ref netId2)).Value == senderID;
					});
					ChatNetworkHandler.OnIncomingObjective?.Invoke(arg, text2, result3, result4);
				}
			}
			catch (Exception ex)
			{
				_log.LogError((object)("[Net] Parse Error: " + ex.Message));
			}
		}
	}
	internal static class CraftingExecutionHandler
	{
		[CompilerGenerated]
		private sealed class <CraftChainRoutine>d__10 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public CraftPlanner.RecipeChain chain;

			public int repeatCount;

			private CharacterBody <body>5__2;

			private NetworkUser <localUser>5__3;

			private Dictionary<int, int> <startCounts>5__4;

			private Dictionary<int, int> <currentProgress>5__5;

			private Queue<ChefRecipe> <craftQueue>5__6;

			private PickupIndex <lastPickup>5__7;

			private int <lastQty>5__8;

			private int <totalSteps>5__9;

			private int <completedSteps>5__10;

			private CraftPlanner.DroneRequirement[] <>7__wrap10;

			private int <>7__wrap11;

			private CraftPlanner.DroneRequirement <req>5__13;

			private CraftPlanner.TradeRequirement[] <>7__wrap13;

			private CraftPlanner.TradeRequirement <req>5__15;

			private ChefRecipe <step>5__16;

			private string <stepName>5__17;

			private CraftingController <controller>5__18;

			private Ingredient[] <>7__wrap18;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<body>5__2 = null;
				<localUser>5__3 = null;
				<startCounts>5__4 = null;
				<currentProgress>5__5 = null;
				<craftQueue>5__6 = null;
				<>7__wrap10 = null;
				<req>5__13 = default(CraftPlanner.DroneRequirement);
				<>7__wrap13 = null;
				<req>5__15 = default(CraftPlanner.TradeRequirement);
				<step>5__16 = null;
				<stepName>5__17 = null;
				<controller>5__18 = null;
				<>7__wrap18 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_06b2: Unknown result type (might be due to invalid IL or missing references)
				//IL_06b7: Unknown result type (might be due to invalid IL or missing references)
				//IL_091a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0924: Expected O, but got Unknown
				//IL_041c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0421: Unknown result type (might be due to invalid IL or missing references)
				//IL_0423: Unknown result type (might be due to invalid IL or missing references)
				//IL_05d7: Unknown result type (might be due to invalid IL or missing references)
				//IL_05dc: Unknown result type (might be due to invalid IL or missing references)
				//IL_0974: Unknown result type (might be due to invalid IL or missing references)
				//IL_0979: Unknown result type (might be due to invalid IL or missing references)
				//IL_0701: Unknown result type (might be due to invalid IL or missing references)
				//IL_0706: Unknown result type (might be due to invalid IL or missing references)
				//IL_08a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_08a8: Unknown result type (might be due to invalid IL or missing references)
				//IL_098c: Unknown result type (might be due to invalid IL or missing references)
				//IL_024c: Unknown result type (might be due to invalid IL or missing references)
				//IL_019e: Unknown result type (might be due to invalid IL or missing references)
				//IL_01a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_01b6: Unknown result type (might be due to invalid IL or missing references)
				//IL_028f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0491: Unknown result type (might be due to invalid IL or missing references)
				//IL_0723: Unknown result type (might be due to invalid IL or missing references)
				//IL_0729: Invalid comparison between Unknown and I4
				//IL_08ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_08f9: Expected O, but got Unknown
				//IL_059e: Unknown result type (might be due to invalid IL or missing references)
				//IL_05a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_074e: Unknown result type (might be due to invalid IL or missing references)
				//IL_063c: Unknown result type (might be due to invalid IL or missing references)
				//IL_0641: Unknown result type (might be due to invalid IL or missing references)
				//IL_09c5: Unknown result type (might be due to invalid IL or missing references)
				//IL_064e: Unknown result type (might be due to invalid IL or missing references)
				//IL_031f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0687: Unknown result type (might be due to invalid IL or missing references)
				List<ChefRecipe> list;
				KeyboardShortcut value;
				List<PickupIndex> desired;
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
				{
					<>1__state = -1;
					CompleteCurrentObjective();
					StateController.BatchMode = false;
					LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
					<body>5__2 = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
					LocalUser firstLocalUser2 = LocalUserManager.GetFirstLocalUser();
					<localUser>5__3 = ((firstLocalUser2 != null) ? firstLocalUser2.currentNetworkUser : null);
					Dictionary<int, int> dictionary = new Dictionary<int, int>();
					if (chain.DroneCostSparse != null)
					{
						CraftPlanner.DroneRequirement[] droneCostSparse = chain.DroneCostSparse;
						for (int j = 0; j < droneCostSparse.Length; j++)
						{
							CraftPlanner.DroneRequirement droneRequirement = droneCostSparse[j];
							if (!dictionary.ContainsKey(droneRequirement.ScrapIndex))
							{
								dictionary[droneRequirement.ScrapIndex] = 0;
							}
							dictionary[droneRequirement.ScrapIndex] += droneRequirement.Count;
						}
					}
					<startCounts>5__4 = new Dictionary<int, int>();
					<currentProgress>5__5 = new Dictionary<int, int>();
					if (chain.DroneCostSparse != null && chain.DroneCostSparse.Length != 0)
					{
						LocalUser firstLocalUser3 = LocalUserManager.GetFirstLocalUser();
						<localUser>5__3 = ((firstLocalUser3 != null) ? firstLocalUser3.currentNetworkUser : null);
						<>7__wrap10 = chain.DroneCostSparse;
						<>7__wrap11 = 0;
						goto IL_03a2;
					}
					goto IL_03bc;
				}
				case 1:
					<>1__state = -1;
					goto IL_0388;
				case 2:
					<>1__state = -1;
					ChatNetworkHandler.SendObjectiveSuccess(<req>5__13.Owner, <req>5__13.ScrapIndex);
					goto IL_0388;
				case 3:
					<>1__state = -1;
					ChatNetworkHandler.SendObjectiveSuccess(<req>5__15.Donor, <req>5__15.UnifiedIndex);
					<req>5__15 = default(CraftPlanner.TradeRequirement);
					<>7__wrap11++;
					goto IL_04f5;
				case 4:
					<>1__state = -1;
					CompleteCurrentObjective();
					<lastPickup>5__7 = PickupIndex.none;
					goto IL_06bc;
				case 5:
					<>1__state = -1;
					goto IL_076d;
				case 6:
					<>1__state = -1;
					goto IL_07bd;
				case 7:
					<>1__state = -1;
					if ((Object)(object)<controller>5__18 != (Object)null && <controller>5__18.AllSlotsFilled() && IngredientsMatchMultiset(<controller>5__18.ingredients, ResolveStepIngredients(<step>5__16)))
					{
						DebugLog.Trace(_log, "[Execution] " + <stepName>5__17 + " verified. Confirming craft...");
						<craftQueue>5__6.Dequeue();
						<completedSteps>5__10++;
						<lastQty>5__8 = <step>5__16.ResultCount;
						<lastPickup>5__7 = GetPickupIndex(<step>5__16);
						NetworkUIPromptController component = ((Component)<controller>5__18).GetComponent<NetworkUIPromptController>();
						if (!Object.op_Implicit((Object)(object)component) || (Object)(object)component.currentParticipantMaster == (Object)null)
						{
							_log.LogWarning((object)"[Execution] Not confirming: participant master is null.");
							return false;
						}
						<controller>5__18.ConfirmSelection();
						<>2__current = (object)new WaitForEndOfFrame();
						<>1__state = 8;
						return true;
					}
					if (Object.op_Implicit((Object)(object)StateController.ActiveCraftingController))
					{
						CraftUI.CloseCraftPanel(StateController.ActiveCraftingController);
					}
					<step>5__16 = null;
					<stepName>5__17 = null;
					<controller>5__18 = null;
					goto IL_0962;
				case 8:
					<>1__state = -1;
					CraftUI.CloseCraftPanel(<controller>5__18);
					<>2__current = (object)new WaitForSeconds(0.2f);
					<>1__state = 9;
					return true;
				case 9:
					<>1__state = -1;
					goto IL_0962;
				case 10:
					{
						<>1__state = -1;
						CompleteCurrentObjective();
						break;
					}
					IL_06bc:
					if (<step>5__16.Ingredients != null)
					{
						<>7__wrap18 = <step>5__16.Ingredients;
						<>7__wrap11 = 0;
						goto IL_077b;
					}
					goto IL_0795;
					IL_050f:
					<craftQueue>5__6 = new Queue<ChefRecipe>();
					list = chain.Steps.Where((ChefRecipe s) => !(s is CraftPlanner.TradeRecipe)).ToList();
					for (int i = 0; i < repeatCount; i++)
					{
						foreach (ChefRecipe item in list)
						{
							<craftQueue>5__6.Enqueue(item);
						}
					}
					<lastPickup>5__7 = PickupIndex.none;
					<lastQty>5__8 = 0;
					<totalSteps>5__9 = <craftQueue>5__6.Count;
					<completedSteps>5__10 = 0;
					StateController.BatchMode = true;
					goto IL_0962;
					IL_03a2:
					if (<>7__wrap11 < <>7__wrap10.Length)
					{
						<req>5__13 = <>7__wrap10[<>7__wrap11];
						if (!<startCounts>5__4.ContainsKey(<req>5__13.ScrapIndex))
						{
							PickupIndex pickupIndexFromUnified = GetPickupIndexFromUnified(<req>5__13.ScrapIndex);
							<startCounts>5__4[<req>5__13.ScrapIndex] = GetOwnedCount(PickupCatalog.GetPickupDef(pickupIndexFromUnified), <body>5__2);
							<currentProgress>5__5[<req>5__13.ScrapIndex] = 0;
						}
						<currentProgress>5__5[<req>5__13.ScrapIndex] += <req>5__13.Count;
						int inventoryGoal = <startCounts>5__4[<req>5__13.ScrapIndex] + <currentProgress>5__5[<req>5__13.ScrapIndex];
						string droneName = GetDroneName(<req>5__13.DroneIdx);
						if ((Object)(object)<req>5__13.Owner == (Object)null || (Object)(object)<req>5__13.Owner == (Object)(object)<localUser>5__3)
						{
							<>2__current = HandleAcquisition(GetPickupIndexFromUnified(<req>5__13.ScrapIndex), inventoryGoal, "Scrap " + droneName + " for");
							<>1__state = 1;
							return true;
						}
						ChatNetworkHandler.SendObjectiveRequest(<req>5__13.Owner, "SCRAP", <req>5__13.ScrapIndex, <req>5__13.Count);
						string text = <req>5__13.Owner?.userName ?? "Teammate";
						<>2__current = HandleAcquisition(GetPickupIndexFromUnified(<req>5__13.ScrapIndex), inventoryGoal, "Wait for " + text + " to scrap " + droneName + " for");
						<>1__state = 2;
						return true;
					}
					<>7__wrap10 = null;
					goto IL_03bc;
					IL_04f5:
					if (<>7__wrap11 < <>7__wrap13.Length)
					{
						<req>5__15 = <>7__wrap13[<>7__wrap11];
						PickupIndex pickupIndexFromUnified2 = GetPickupIndexFromUnified(<req>5__15.UnifiedIndex);
						int inventoryGoal2 = GetOwnedCount(PickupCatalog.GetPickupDef(pickupIndexFromUnified2), <body>5__2) + <req>5__15.Count;
						ChatNetworkHandler.SendObjectiveRequest(<req>5__15.Donor, "TRADE", <req>5__15.UnifiedIndex, <req>5__15.Count);
						string text2 = <req>5__15.Donor?.userName ?? "Ally";
						<>2__current = HandleAcquisition(pickupIndexFromUnified2, inventoryGoal2, "Wait for " + text2 + " to trade");
						<>1__state = 3;
						return true;
					}
					<>7__wrap13 = null;
					goto IL_050f;
					IL_077b:
					if (<>7__wrap11 < <>7__wrap18.Length)
					{
						Ingredient ingredient = <>7__wrap18[<>7__wrap11];
						value = CookBook.AbortKey.Value;
						if (((KeyboardShortcut)(ref value)).IsPressed())
						{
							Abort();
							return false;
						}
						if (!ingredient.IsItem && (int)ingredient.EquipIndex != -1)
						{
							SetObjectiveText("Preparing " + <stepName>5__17 + "...");
							<>2__current = EnsureEquipmentIsActive(<body>5__2, ingredient.EquipIndex);
							<>1__state = 5;
							return true;
						}
						goto IL_076d;
					}
					<>7__wrap18 = null;
					goto IL_0795;
					IL_03bc:
					if (chain.AlliedTradeSparse != null && chain.AlliedTradeSparse.Length != 0)
					{
						<>7__wrap13 = chain.AlliedTradeSparse;
						<>7__wrap11 = 0;
						goto IL_04f5;
					}
					goto IL_050f;
					IL_076d:
					<>7__wrap11++;
					goto IL_077b;
					IL_0795:
					if ((Object)(object)StateController.ActiveCraftingController == (Object)null)
					{
						<>2__current = EnsureCraftingControllerOpen();
						<>1__state = 6;
						return true;
					}
					goto IL_07bd;
					IL_0388:
					<req>5__13 = default(CraftPlanner.DroneRequirement);
					<>7__wrap11++;
					goto IL_03a2;
					IL_07bd:
					<controller>5__18 = StateController.ActiveCraftingController;
					if (!Object.op_Implicit((Object)(object)<controller>5__18))
					{
						Cleanup(closeUi: true);
						return false;
					}
					desired = ResolveStepIngredients(<step>5__16);
					<>2__current = SubmitIngredientsClientSafe(<controller>5__18, desired);
					<>1__state = 7;
					return true;
					IL_0962:
					if (<craftQueue>5__6.Count > 0)
					{
						value = CookBook.AbortKey.Value;
						if (((KeyboardShortcut)(ref value)).IsPressed())
						{
							Abort();
							return false;
						}
						LocalUser firstLocalUser4 = LocalUserManager.GetFirstLocalUser();
						<body>5__2 = ((firstLocalUser4 != null) ? firstLocalUser4.cachedBody : null);
						if (!Object.op_Implicit((Object)(object)<body>5__2))
						{
							Abort();
							return false;
						}
						<step>5__16 = <craftQueue>5__6.Peek();
						<stepName>5__17 = GetStepName(<step>5__16);
						if (<lastPickup>5__7 != PickupIndex.none)
						{
							SetObjectiveText("Collect " + Language.GetString(PickupCatalog.GetPickupDef(<lastPickup>5__7)?.nameToken ?? "Result"));
							<>2__current = WaitForPendingPickup(<lastPickup>5__7, <lastQty>5__8);
							<>1__state = 4;
							return true;
						}
						goto IL_06bc;
					}
					if (<lastPickup>5__7 != PickupIndex.none)
					{
						StateController.BatchMode = false;
						SetObjectiveText("Collect " + Language.GetString(PickupCatalog.GetPickupDef(<lastPickup>5__7)?.nameToken ?? "Result"));
						<>2__current = WaitForPendingPickup(<lastPickup>5__7, <lastQty>5__8);
						<>1__state = 10;
						return true;
					}
					break;
				}
				DebugLog.Trace(_log, $"[ExecutionHandler] Finished {<completedSteps>5__10}/{<totalSteps>5__9} steps.");
				Cleanup(closeUi: true);
				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 <EnsureCraftingControllerOpen>d__12 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			private float <t>5__2;

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

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

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

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

			private bool MoveNext()
			{
				//IL_002f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0034: Unknown result type (might be due to invalid IL or missing references)
				//IL_00d3: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00e7: 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_0141: Unknown result type (might be due to invalid IL or missing references)
				//IL_014b: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<t>5__2 = 0f;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (!IsCraftingSessionReady(StateController.ActiveCraftingController))
				{
					KeyboardShortcut value = CookBook.AbortKey.Value;
					if (((KeyboardShortcut)(ref value)).IsPressed())
					{
						Abort();
						return false;
					}
					LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
					CharacterBody val = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
					Interactor val2 = (Object.op_Implicit((Object)(object)val) ? ((Component)val).GetComponent<Interactor>() : null);
					if (!Object.op_Implicit((Object)(object)StateController.TargetCraftingObject) && Object.op_Implicit((Object)(object)val))
					{
						StateController.TargetCraftingObject = TryResolveChefStationObject(val);
					}
					if (!Object.op_Implicit((Object)(object)StateController.TargetCraftingObject) || !Object.op_Implicit((Object)(object)val) || !Object.op_Implicit((Object)(object)val2))
					{
						_log.LogWarning((object)"[Execution] Lost target/body/interactor while trying to open crafting UI. Aborting.");
						Abort();
						return false;
					}
					SetObjectiveText("Approach Wandering CHEF");
					float num = val2.maxInteractionDistance + 6f;
					Vector3 val3 = val.corePosition - StateController.TargetCraftingObject.transform.position;
					if (((Vector3)(ref val3)).sqrMagnitude <= num * num)
					{
						val2.AttemptInteraction(StateController.TargetCraftingObject);
					}
					<t>5__2 += Time.unscaledDeltaTime;
					if (<t>5__2 >= 12f)
					{
						_log.LogWarning((object)"[Execution] Timed out opening crafting UI.");
						Cleanup(closeUi: true);
						return false;
					}
					<>2__current = (object)new WaitForSecondsRealtime(0.2f);
					<>1__state = 1;
					return true;
				}
				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 <EnsureEquipmentIsActive>d__23 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public CharacterBody body;

			public EquipmentIndex target;

			private Inventory <inv>5__2;

			private int <targetSlot>5__3;

			private int <targetSet>5__4;

			private GenericSkill <skill>5__5;

			private float <timeout>5__6;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<inv>5__2 = null;
				<skill>5__5 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0045: Unknown result type (might be due to invalid IL or missing references)
				//IL_004b: Invalid comparison between Unknown and I4
				//IL_013e: Unknown result type (might be due to invalid IL or missing references)
				//IL_0148: 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_02bf: Unknown result type (might be due to invalid IL or missing references)
				//IL_02c9: Expected O, but got Unknown
				//IL_026a: Unknown result type (might be due to invalid IL or missing references)
				//IL_0098: Unknown result type (might be due to invalid IL or missing references)
				//IL_009d: Unknown result type (might be due to invalid IL or missing references)
				//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
				int num;
				int equipmentSetCount2;
				int num2;
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
				{
					<>1__state = -1;
					<inv>5__2 = body.inventory;
					if (!Object.op_Implicit((Object)(object)<inv>5__2) || (int)target == -1)
					{
						return false;
					}
					int activeEquipmentSlot = <inv>5__2.activeEquipmentSlot;
					int equipmentSlotCount = <inv>5__2.GetEquipmentSlotCount();
					<targetSlot>5__3 = -1;
					<targetSet>5__4 = -1;
					for (int i = 0; i < equipmentSlotCount; i++)
					{
						int equipmentSetCount = <inv>5__2.GetEquipmentSetCount((uint)i);
						for (int j = 0; j < equipmentSetCount; j++)
						{
							if (<inv>5__2.GetEquipment((uint)i, (uint)j).equipmentIndex == target)
							{
								<targetSlot>5__3 = i;
								<targetSet>5__4 = j;
								break;
							}
						}
						if (<targetSlot>5__3 != -1)
						{
							break;
						}
					}
					if (<targetSlot>5__3 == -1)
					{
						return false;
					}
					if (<targetSlot>5__3 != activeEquipmentSlot)
					{
						<skill>5__5 = body.skillLocator?.special;
						if (Object.op_Implicit((Object)(object)<skill>5__5))
						{
							if (Object.op_Implicit((Object)(object)StateController.ActiveCraftingController))
							{
								CraftUI.CloseCraftPanel(StateController.ActiveCraftingController);
							}
							goto IL_0158;
						}
						goto IL_01ef;
					}
					goto IL_01f6;
				}
				case 1:
					<>1__state = -1;
					goto IL_0158;
				case 2:
					<>1__state = -1;
					goto IL_01cf;
				case 3:
					{
						<>1__state = -1;
						goto IL_02d9;
					}
					IL_02d9:
					if (<inv>5__2.activeEquipmentSet[<inv>5__2.activeEquipmentSlot] != <targetSet>5__4 && <timeout>5__6 > 0f)
					{
						<timeout>5__6 -= 0.1f;
						<>2__current = (object)new WaitForSeconds(0.1f);
						<>1__state = 3;
						return true;
					}
					break;
					IL_01cf:
					if (<inv>5__2.activeEquipmentSlot != <targetSlot>5__3 && <timeout>5__6 > 0f)
					{
						<timeout>5__6 -= 0.1f;
						<>2__current = (object)new WaitForSeconds(0.1f);
						<>1__state = 2;
						return true;
					}
					goto IL_01ef;
					IL_01f6:
					num = <inv>5__2.activeEquipmentSet[<inv>5__2.activeEquipmentSlot];
					equipmentSetCount2 = <inv>5__2.GetEquipmentSetCount((uint)<inv>5__2.activeEquipmentSlot);
					if (<targetSet>5__4 == num)
					{
						break;
					}
					if (Object.op_Implicit((Object)(object)StateController.ActiveCraftingController))
					{
						CraftUI.CloseCraftPanel(StateController.ActiveCraftingController);
					}
					num2 = (<targetSet>5__4 - num + equipmentSetCount2) % equipmentSetCount2;
					DebugLog.Trace(_log, $"[Execution] Cycling sets ({num2} clicks) for {target}.");
					for (int k = 0; k < num2; k++)
					{
						<inv>5__2.CallCmdSwitchToNextEquipmentInSet();
					}
					<timeout>5__6 = 2f;
					goto IL_02d9;
					IL_01ef:
					<skill>5__5 = null;
					goto IL_01f6;
					IL_0158:
					if (!<skill>5__5.CanExecute())
					{
						<>2__current = (object)new WaitForSeconds(0.1f);
						<>1__state = 1;
						return true;
					}
					DebugLog.Trace(_log, $"[Execution] Retooling to Slot {<targetSlot>5__3}.");
					<skill>5__5.ExecuteIfReady();
					<timeout>5__6 = 1f;
					goto IL_01cf;
				}
				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 <HandleAcquisition>d__25 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public PickupIndex pi;

			public int inventoryGoal;

			public string actionPrefix;

			private CharacterBody <body>5__2;

			private PickupDef <def>5__3;

			private string <itemName>5__4;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<body>5__2 = null;
				<def>5__3 = null;
				<itemName>5__4 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0033: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b5: Unknown result type (might be due to invalid IL or missing references)
				//IL_00bf: Expected O, but got Unknown
				int num = <>1__state;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
				}
				else
				{
					<>1__state = -1;
					LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
					<body>5__2 = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
					<def>5__3 = PickupCatalog.GetPickupDef(pi);
					if (!Object.op_Implicit((Object)(object)<body>5__2) || <def>5__3 == null)
					{
						return false;
					}
					<itemName>5__4 = Language.GetString(<def>5__3.nameToken);
				}
				int ownedCount = GetOwnedCount(<def>5__3, <body>5__2);
				int num2 = inventoryGoal - ownedCount;
				if (num2 > 0)
				{
					SetObjectiveText($"{actionPrefix} {<itemName>5__4} <style=cSub>(Need {num2})</style>");
					<>2__current = (object)new WaitForSeconds(0.1f);
					<>1__state = 1;
					return true;
				}
				CompleteCurrentObjective();
				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 <SubmitIngredientsClientSafe>d__17 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public CraftingController controller;

			public List<PickupIndex> desired;

			private NetworkUIPromptController <prompt>5__2;

			private float <t>5__3;

			private float <clearBudget>5__4;

			private float <syncBudget>5__5;

			private int <k>5__6;

			private PickupIndex <want>5__7;

			private bool <inserted>5__8;

			private float <insertBudget>5__9;

			private int <filledBefore>5__10;

			private int <wantCountBefore>5__11;

			private float <progressBudget>5__12;

			private bool <progressed>5__13;

			private float <settleBudget>5__14;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0611: Unknown result type (might be due to invalid IL or missing references)
				//IL_04ea: Unknown result type (might be due to invalid IL or missing references)
				//IL_05a3: Unknown result type (might be due to invalid IL or missing references)
				//IL_0483: Unknown result type (might be due to invalid IL or missing references)
				//IL_0275: Unknown result type (might be due to invalid IL or missing references)
				//IL_027a: Unknown result type (might be due to invalid IL or missing references)
				//IL_01ef: Unknown result type (might be due to invalid IL or missing references)
				//IL_01f4: Unknown result type (might be due to invalid IL or missing references)
				//IL_0326: Unknown result type (might be due to invalid IL or missing references)
				//IL_033d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0384: Unknown result type (might be due to invalid IL or missing references)
				//IL_0389: Unknown result type (might be due to invalid IL or missing references)
				//IL_039e: Unknown result type (might be due to invalid IL or missing references)
				//IL_03b5: Unknown result type (might be due to invalid IL or missing references)
				//IL_03b7: Unknown result type (might be due to invalid IL or missing references)
				//IL_03bc: Unknown result type (might be due to invalid IL or missing references)
				//IL_03c9: Unknown result type (might be due to invalid IL or missing references)
				//IL_0403: Unknown result type (might be due to invalid IL or missing references)
				//IL_0425: Unknown result type (might be due to invalid IL or missing references)
				//IL_042f: Expected O, but got Unknown
				//IL_018b: 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)
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (!Object.op_Implicit((Object)(object)controller) || desired == null)
					{
						return false;
					}
					<prompt>5__2 = ((Component)controller).GetComponent<NetworkUIPromptController>();
					<t>5__3 = 2f;
					goto IL_0098;
				case 1:
					<>1__state = -1;
					goto IL_0098;
				case 2:
					<>1__state = -1;
					goto IL_023d;
				case 3:
					<>1__state = -1;
					goto IL_05c9;
				case 4:
					<>1__state = -1;
					goto IL_05c9;
				case 5:
					<>1__state = -1;
					<progressBudget>5__12 = 1f;
					<progressed>5__13 = false;
					goto IL_04c7;
				case 6:
					<>1__state = -1;
					goto IL_04c7;
				case 7:
					<>1__state = -1;
					goto IL_0583;
				case 8:
					{
						<>1__state = -1;
						break;
					}
					IL_04c7:
					if (<progressBudget>5__12 > 0f)
					{
						if (!Object.op_Implicit((Object)(object)controller))
						{
							return false;
						}
						PickupIndex[] ingredients = controller.ingredients;
						if (CountFilled(ingredients) < <filledBefore>5__10 + 1 || CountOf(ingredients, <want>5__7) <= <wantCountBefore>5__11)
						{
							<progressBudget>5__12 -= Time.unscaledDeltaTime;
							<>2__current = null;
							<>1__state = 6;
							return true;
						}
						<progressed>5__13 = true;
					}
					if (!<progressed>5__13)
					{
						DebugLog.Trace(_log, $"[Crafting] No fill-progress observed for {<want>5__7}, retrying...");
						<insertBudget>5__9 -= 0.25f;
						goto IL_05c9;
					}
					<settleBudget>5__14 = 0.75f;
					goto IL_0583;
					IL_05c9:
					if (!<inserted>5__8 && <insertBudget>5__9 > 0f)
					{
						if (!Object.op_Implicit((Object)(object)controller))
						{
							return false;
						}
						if (controller.AllSlotsFilled() && !IngredientsMatchMultiset(controller.ingredients, desired))
						{
							_log.LogWarning((object)"[Crafting] Station became full with wrong ingredients. Aborting insert to avoid accidental confirm.");
							return false;
						}
						Option[] options = ((PickupPickerController)controller).options;
						if (options == null || options.Length == 0)
						{
							<insertBudget>5__9 -= Time.unscaledDeltaTime;
							<>2__current = null;
							<>1__state = 3;
							return true;
						}
						if (!TryFindChoiceIndex(controller, <want>5__7, out var choiceIndex) || !IsChoiceIndexStillValid(controller, choiceIndex, <want>5__7))
						{
							<insertBudget>5__9 -= Time.unscaledDeltaTime;
							<>2__current = null;
							<>1__state = 4;
							return true;
						}
						Option val = ((PickupPickerController)controller).options[choiceIndex];
						DebugLog.Trace(_log, $"[Crafting] Pick want={<want>5__7} choiceIndex={choiceIndex} optPickup={val.pickup.pickupIndex} available={val.available}");
						<filledBefore>5__10 = CountFilled(controller.ingredients);
						<wantCountBefore>5__11 = CountOf(controller.ingredients, <want>5__7);
						SubmitChoiceToCraftingController(controller, choiceIndex);
						<>2__current = (object)new WaitForSecondsRealtime(0.1f);
						<>1__state = 5;
						return true;
					}
					if (!<inserted>5__8)
					{
						_log.LogWarning((object)$"[Crafting] Failed to insert ingredient {<k>5__6 + 1}/{desired.Count}: {<want>5__7}");
						return false;
					}
					<k>5__6++;
					goto IL_0639;
					IL_0639:
					if (<k>5__6 < desired.Count)
					{
						if (!Object.op_Implicit((Object)(object)controller))
						{
							return false;
						}
						<want>5__7 = desired[<k>5__6];
						<inserted>5__8 = false;
						<insertBudget>5__9 = 2f;
						goto IL_05c9;
					}
					<syncBudget>5__5 = 2f;
					break;
					IL_0583:
					if (<settleBudget>5__14 > 0f)
					{
						if (!Object.op_Implicit((Object)(object)controller))
						{
							return false;
						}
						if (!IngredientsMatchPrefixMultiset(controller.ingredients, desired, <k>5__6 + 1))
						{
							<settleBudget>5__14 -= Time.unscaledDeltaTime;
							<>2__current = null;
							<>1__state = 7;
							return true;
						}
						<inserted>5__8 = true;
					}
					if (!<inserted>5__8)
					{
						DebugLog.Trace(_log, $"[Crafting] Change observed but state did not settle for {<want>5__7}, retrying...");
						<insertBudget>5__9 -= 0.25f;
					}
					goto IL_05c9;
					IL_024d:
					<k>5__6 = 0;
					goto IL_0639;
					IL_023d:
					if (<clearBudget>5__4 > 0f)
					{
						if (!Object.op_Implicit((Object)(object)controller))
						{
							return false;
						}
						PickupIndex[] ingredients2 = controller.ingredients;
						if (ingredients2 != null)
						{
							bool flag = false;
							for (int i = 0; i < ingredients2.Length; i++)
							{
								if (ingredients2[i] != PickupIndex.none)
								{
									flag = true;
									break;
								}
							}
							if (!flag)
							{
								goto IL_024d;
							}
						}
						<clearBudget>5__4 -= Time.unscaledDeltaTime;
						<>2__current = null;
						<>1__state = 2;
						return true;
					}
					goto IL_024d;
					IL_0098:
					if (<t>5__3 > 0f && (!Object.op_Implicit((Object)(object)controller) || !Object.op_Implicit((Object)(object)<prompt>5__2) || (Object)(object)<prompt>5__2.currentParticipantMaster == (Object)null))
					{
						<t>5__3 -= Time.unscaledDeltaTime;
						<>2__current = null;
						<>1__state = 1;
						return true;
					}
					if (!Object.op_Implicit((Object)(object)controller) || !Object.op_Implicit((Object)(object)<prompt>5__2) || (Object)(object)<prompt>5__2.currentParticipantMaster == (Object)null)
					{
						_log.LogError((object)"[Crafting] Participant Master not ready. Station not synced.");
						return false;
					}
					if (desired.Count != controller.ingredientCount)
					{
						_log.LogWarning((object)$"[Crafting] Ingredient count mismatch. step needs {desired.Count}, controller has {controller.ingredientCount} slots.");
						return false;
					}
					for (int j = 0; j < controller.ingredientCount; j++)
					{
						if (controller.ingredients != null && j < controller.ingredients.Length && controller.ingredients[j] != PickupIndex.none)
						{
							controller.ClearSlot(j);
						}
					}
					<clearBudget>5__4 = 1f;
					goto IL_023d;
				}
				if (<syncBudget>5__5 > 0f)
				{
					if (!Object.op_Implicit((Object)(object)controller))
					{
						return false;
					}
					if (IngredientsMatchMultiset(controller.ingredients, desired))
					{
						return false;
					}
					<syncBudget>5__5 -= Time.unscaledDeltaTime;
					<>2__current = null;
					<>1__state = 8;
					return true;
				}
				_log.LogWarning((object)"[Crafting] Timed out waiting for ingredient sync.");
				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 <WaitForPendingPickup>d__26 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public PickupIndex pickupIndex;

			public int expectedGain;

			private CharacterBody <body>5__2;

			private PickupDef <def>5__3;

			private int <targetCount>5__4;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<body>5__2 = null;
				<def>5__3 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00d0: Unknown result type (might be due to invalid IL or missing references)
				//IL_00da: Expected O, but got Unknown
				//IL_0054: Unknown result type (might be due to invalid IL or missing references)
				int num = <>1__state;
				if (num != 0)
				{
					if (num != 1)
					{
						return false;
					}
					<>1__state = -1;
				}
				else
				{
					<>1__state = -1;
					LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
					<body>5__2 = ((firstLocalUser != null) ? firstLocalUser.cachedBody : null);
					if (!Object.op_Implicit((Object)(object)<body>5__2) || !Object.op_Implicit((Object)(object)<body>5__2.inventory))
					{
						return false;
					}
					<def>5__3 = PickupCatalog.GetPickupDef(pickupIndex);
					if (<def>5__3 == null)
					{
						return false;
					}
					<targetCount>5__4 = GetOwnedCount(<def>5__3, <body>5__2) + expectedGain;
				}
				if (GetOwnedCount(<def>5__3, <body>5__2) >= <targetCount>5__4)
				{
					DebugLog.Trace(_log, "[Chain] Confirmed pickup of " + <def>5__3.internalName + ".");
					return false;
				}
				<>2__current = (object)new WaitForSeconds(0.1f);
				<>1__state = 1;
				return true;
			}

			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 ManualLogSource _log;

		private static ObjectiveTracker.ObjectiveToken _currentObjective;

		private static Coroutine _craftingRoutine;

		private static MonoBehaviour _runner;

		public static bool IsAutoCrafting => _craftingRoutine != null;

		internal static void Init(ManualLogSource log, MonoBehaviour runner)
		{
			_log = log;
			_runner = runner;
		}

		public static void ExecuteChain(CraftPlanner.RecipeChain chain, int repeatCount)
		{
			if (CookBook.isDebugMode)
			{
				DumpChain(chain, repeatCount);
			}
			Abort();
			_craftingRoutine = _runner.StartCoroutine(CraftChainRoutine(chain, repeatCount));
		}

		private static void Cleanup(bool closeUi = false)
		{
			_craftingRoutine = null;
			StateController.BatchMode = false;
			CompleteCurrentObjective();
			if (closeUi && Object.op_Implicit((Object)(object)StateController.ActiveCraftingController))
			{
				CraftUI.CloseCraftPanel(StateController.ActiveCraftingController);
			}
		}

		public static void Abort()
		{
			if ((Object)(object)_runner != (Object)null && _craftingRoutine != null)
			{
				_runner.StopCoroutine(_craftingRoutine);
			}
			Cleanup(closeUi: true);
		}

		[IteratorStateMachine(typeof(<CraftChainRoutine>d__10))]
		private static IEnumerator CraftChainRoutine(CraftPlanner.RecipeChain chain, int repeatCount)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <CraftChainRoutine>d__10(0)
			{
				chain = chain,
				repeatCount = repeatCount
			};
		}

		private static bool IsCraftingSessionReady(CraftingController c)
		{
			if (!Object.op_Implicit((Object)(object)c))
			{
				return false;
			}
			NetworkUIPromptController component = ((Component)c).GetComponent<NetworkUIPromptController>();
			if (!Object.op_Implicit((Object)(object)component))
			{
				return false;
			}
			if ((Object)(object)component.currentParticipantMaster == (Object)null)
			{
				return false;
			}
			if (!component.isDisplaying)
			{
				return false;
			}
			CraftingPanel[] array = Object.FindObjectsOfType<CraftingPanel>();
			for (int i = 0; i < array.Length; i++)
			{
				if (Object.op_Implicit((Object)(object)array[i]) && (Object)(object)array[i].craftingController == (Object)(object)c)
				{
					return true;
				}
			}
			return false;
		}

		[IteratorStateMachine(typeof(<EnsureCraftingControllerOpen>d__12))]
		private static IEnumerator EnsureCraftingControllerOpen()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <EnsureCraftingControllerOpen>d__12(0);
		}

		private static List<PickupIndex> ResolveStepIngredients(ChefRecipe step)
		{
			//IL_0070: 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_007a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0060: Unknown result type (might be due to invalid IL or missing references)
			//IL_0065: Unknown result type (might be due to invalid IL or missing references)
			//IL_006a: 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)
			List<PickupIndex> list = new List<PickupIndex>(step.Ingredients.Sum((Ingredient i) => Mathf.Max(0, i.Count)));
			Ingredient[] ingredients = step.Ingredients;
			for (int j = 0; j < ingredients.Length; j++)
			{
				Ingredient ingredient = ingredients[j];
				int num = Mathf.Max(0, ingredient.Count);
				if (num != 0)
				{
					PickupIndex item = ((!ingredient.IsItem) ? PickupCatalog.FindPickupIndex(ingredient.EquipIndex) : PickupCatalog.FindPickupIndex(ingredient.ItemIndex));
					for (int k = 0; k < num; k++)
					{
						list.Add(item);
					}
				}
			}
			return list;
		}

		private static bool TryFindChoiceIndex(CraftingController c, PickupIndex desired, out int choiceIndex)
		{
			//IL_001f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			choiceIndex = -1;
			Option[] options = ((PickupPickerController)c).options;
			if (options == null)
			{
				return false;
			}
			for (int i = 0; i < options.Length; i++)
			{
				if (options[i].pickup.pickupIndex == desired)
				{
					choiceIndex = i;
					return true;
				}
			}
			return false;
		}

		private static bool IsChoiceIndexStillValid(CraftingController c, int idx, PickupIndex desired)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_001b: Unknown result type (might be due to invalid IL or missing references)
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			Option[] options = ((PickupPickerController)c).options;
			if (options == null)
			{
				return false;
			}
			if ((uint)idx >= (uint)options.Length)
			{
				return false;
			}
			Option val = options[idx];
			if (val.available)
			{
				return val.pickup.pickupIndex == desired;
			}
			return false;
		}

		private static void SubmitChoiceToCraftingController(CraftingController c, int choiceIndex)
		{
			NetworkUIPromptController component = ((Component)c).GetComponent<NetworkUIPromptController>();
			if (Object.op_Implicit((Object)(object)component))
			{
				NetworkWriter val = component.BeginMessageToServer();
				if (val != null)
				{
					val.Write((byte)0);
					val.Write(choiceIndex);
					component.FinishMessageToServer(val);
				}
			}
		}

		[IteratorStateMachine(typeof(<SubmitIngredientsClientSafe>d__17))]
		private static IEnumerator SubmitIngredientsClientSafe(CraftingController controller, List<PickupIndex> desired)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <SubmitIngredientsClientSafe>d__17(0)
			{
				controller = controller,
				desired = desired
			};
		}

		private static bool IngredientsMatchPrefixMultiset(PickupIndex[] current, List<PickupIndex> desired, int insertedCount)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_004a: Unknown result type (might be due to invalid IL or missing references)
			//IL_004f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Unknown result type (might be due to invalid IL or missing references)
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_005f: Unknown result type (might be due to invalid IL or missing references)
			if (current == null || desired == null)
			{
				return false;
			}
			Dictionary<int, int> dictionary = new Dictionary<int, int>();
			for (int i = 0; i < insertedCount; i++)
			{
				int value = desired[i].value;
				dictionary.TryGetValue(value, out var value2);
				dictionary[value] = value2 + 1;
			}
			Dictionary<int, int> dictionary2 = new Dictionary<int, int>();
			foreach (PickupIndex val in current)
			{
				if (!(val == PickupIndex.none))
				{
					int value3 = val.value;
					dictionary2.TryGetValue(value3, out var value4);
					dictionary2[value3] = value4 + 1;
				}
			}
			if (dictionary2.Count != dictionary.Count)
			{
				return false;
			}
			foreach (KeyValuePair<int, int> item in dictionary)
			{
				if (!dictionary2.TryGetValue(item.Key, out var value5))
				{
					return false;
				}
				if (value5 != item.Value)
				{
					return false;
				}
			}
			return true;
		}

		private static bool IngredientsMatchMultiset(PickupIndex[] actualSlots, List<PickupIndex> desired)
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_002a: Unknown result type (might be due to invalid IL or missing references)
			//IL_002b: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Unknown result type (might be due to invalid IL or missing references)
			//IL_003c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0064: Unknown result type (might be due to invalid IL or missing references)
			//IL_0069: Unknown result type (might be due to invalid IL or missing references)
			//IL_006c: Unknown result type (might be due to invalid IL or missing references)
			//IL_006f: 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)
			if (actualSlots == null)
			{
				return false;
			}
			if (actualSlots.Length != desired.Count)
			{
				return false;
			}
			Dictionary<PickupIndex, int> dictionary = new Dictionary<PickupIndex, int>();
			Dictionary<PickupIndex, int> dictionary2 = new Dictionary<PickupIndex, int>();
			foreach (PickupIndex val in actualSlots)
			{
				if (val == PickupIndex.none)
				{
					return false;
				}
				dictionary[val] = ((!dictionary.TryGetValue(val, out var value)) ? 1 : (value + 1));
			}
			for (int j = 0; j < desired.Count; j++)
			{
				PickupIndex key = desired[j];
				dictionary2[key] = ((!dictionary2.TryGetValue(key, out var value2)) ? 1 : (value2 + 1));
			}
			if (dictionary.Count != dictionary2.Count)
			{
				return false;
			}
			foreach (KeyValuePair<PickupIndex, int> item in dictionary)
			{
				if (!dictionary2.TryGetValue(item.Key, out var value3))
				{
					return false;
				}
				if (value3 != item.Value)
				{
					return false;
				}
			}
			return true;
		}

		private static int HashIngredients(PickupIndex[] arr)
		{
			if (arr == null)
			{
				return 0;
			}
			int num = 17;
			for (int i = 0; i < arr.Length; i++)
			{
				num = num * 31 + arr[i].value;
			}
			return num;
		}

		private static int CountFilled(PickupIndex[] slots)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (slots == null)
			{
				return 0;
			}
			int num = 0;
			for (int i = 0; i < slots.Length; i++)
			{
				if (slots[i] != PickupIndex.none)
				{
					num++;
				}
			}
			return num;
		}

		private static int CountOf(PickupIndex[] slots, PickupIndex p)
		{
			//IL_000d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0012: Unknown result type (might be due to invalid IL or missing references)
			if (slots == null)
			{
				return 0;
			}
			int num = 0;
			for (int i = 0; i < slots.Length; i++)
			{
				if (slots[i] == p)
				{
					num++;
				}
			}
			return num;
		}

		[IteratorStateMachine(typeof(<EnsureEquipmentIsActive>d__23))]
		private static IEnumerator EnsureEquipmentIsActive(CharacterBody body, EquipmentIndex target)
		{
			//IL_000e: Unknown result type (might be due to invalid IL or missing references)
			//IL_000f: Unknown result type (might be due to invalid IL or missing references)
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <EnsureEquipmentIsActive>d__23(0)
			{
				body = body,
				target = target
			};
		}

		private static GameObject TryResolveChefStationObject(CharacterBody body)
		{
			//IL_0022: 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_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: 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_0052: Unknown result type (might be due to invalid IL or missing references)
			if (!Object.op_Implicit((Object)(object)body))
			{
				return null;
			}
			MealPrepController[] array = Object.FindObjectsOfType<MealPrepController>();
			if (array == null || array.Length == 0)
			{
				return null;
			}
			MealPrepController val = null;
			float num = float.PositiveInfinity;
			Vector3 corePosition = body.corePosition;
			MealPrepController[] array2 = array;
			foreach (MealPrepController val2 in array2)
			{
				if (Object.op_Implicit((Object)(object)val2))
				{
					Vector3 val3 = ((Component)val2).transform.position - corePosition;
					float sqrMagnitude = ((Vector3)(ref val3)).sqrMagnitude;
					if (sqrMagnitude < num)
					{
						num = sqrMagnitude;
						val = val2;
					}
				}
			}
			if (!Object.op_Implicit((Object)(object)val))
			{
				return null;
			}
			IInteractable componentInChildren = ((Component)val).GetComponentInChildren<IInteractable>();
			Component val4 = (Component)(object)((componentInChildren is Component) ? componentInChildren : null);
			if (!Object.op_Implicit((Object)(object)val4))
			{
				return ((Component)val).gameObject;
			}
			return val4.gameObject;
		}

		[IteratorStateMachine(typeof(<HandleAcquisition>d__25))]
		private static IEnumerator HandleAcquisition(PickupIndex pi, int inventoryGoal, string actionPrefix)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <HandleAcquisition>d__25(0)
			{
				pi = pi,
				inventoryGoal = inventoryGoal,
				actionPrefix = actionPrefix
			};
		}

		[IteratorStateMachine(typeof(<WaitForPendingPickup>d__26))]
		private static IEnumerator WaitForPendingPickup(PickupIndex pickupIndex, int expectedGain)
		{
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0008: Unknown result type (might be due to invalid IL or missing references)
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForPendingPickup>d__26(0)
			{
				pickupIndex = pickupIndex,
				expectedGain = expectedGain
			};
		}

		private static int GetOwnedCount(PickupDef def, CharacterBody body)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Invalid comparison between Unknown and I4
			//IL_0010: Unknown result type (might be due to invalid IL or missing references)
			//IL_0047: Unknown result type (might be due to invalid IL or missing references)
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0052: Unknown result type (might be due to invalid IL or missing references)
			if ((int)def.itemIndex != -1)
			{
				return body.inventory.GetItemCountPermanent(def.itemIndex);
			}
			if ((int)def.equipmentIndex != -1)
			{
				Inventory inventory = body.inventory;
				int equipmentSlotCount = inventory.GetEquipmentSlotCount();
				for (int i = 0; i < equipmentSlotCount; i++)
				{
					int equipmentSetCount = inventory.GetEquipmentSetCount((uint)i);
					for (int j = 0; j < equipmentSetCount; j++)
					{
						if (inventory.GetEquipment((uint)i, (uint)j).equipmentIndex == def.equipmentIndex)
						{
							return 1;
						}
					}
				}
			}
			return 0;
		}

		private static string GetStepName(ChefRecipe step)
		{
			string text = ((step.ResultIndex < ItemCatalog.itemCount) ? Language.GetString(ItemCatalog.GetItemDef((ItemIndex)step.ResultIndex)?.nameToken) : Language.GetString(EquipmentCatalog.GetEquipmentDef((EquipmentIndex)(step.ResultIndex - ItemCatalog.itemCount))?.nameToken));
			if (step is CraftPlanner.TradeRecipe)
			{
				return "<style=cIsUtility>Trade: " + text + "</style>";
			}
			return text;
		}

		private static PickupIndex GetPickupIndex(ChefRecipe step)
		{
			//IL_0025: Unknown result type (might be due to invalid IL or missing references)
			//IL_0013: Unknown result type (might be due to invalid IL or missing references)
			if (step.ResultIndex < ItemCatalog.itemCount)
			{
				return PickupCatalog.FindPickupIndex((ItemIndex)step.ResultIndex);
			}
			return PickupCatalog.FindPickupIndex((EquipmentIndex)(step.ResultIndex - ItemCatalog.itemCount));
		}

		private static string GetDroneName(DroneIndex droneIdx)
		{
			//IL_0000: Unknown result type (might be due to invalid IL or missing references)
			//IL_0002: Invalid comparison between Unknown and I4
			//IL_0004: Unknown result type (might be due to invalid IL or missing references)
			if ((int)droneIdx != -1)
			{
				GameObject val = DroneCatalog.GetDroneDef(droneIdx)?.bodyPrefab;
				if (Object.op_Implicit((Object)(object)val))
				{
					CharacterBody component = val.GetComponent<CharacterBody>();
					if (component != null)
					{
						return Language.GetString(component.baseNameToken);
					}
				}
			}
			return "Drone";
		}

		private static PickupIndex GetPickupIndexFromUnified(int unifiedIndex)
		{
			//IL_0016: Unknown result type (might be due to invalid IL or missing references)
			//IL_0009: Unknown result type (might be due to invalid IL or missing references)
			if (unifiedIndex < ItemCatalog.itemCount)
			{
				return PickupCatalog.FindPickupIndex((ItemIndex)unifiedIndex);
			}
			return PickupCatalog.FindPickupIndex((EquipmentIndex)(unifiedIndex - ItemCatalog.itemCount));
		}

		private static void SetObjectiveText(string text)
		{
			if ((Object)(object)_currentObjective == (Object)null)
			{
				_currentObjective = ObjectiveTracker.CreateObjective(text);
			}
			else
			{
				_currentObjective.UpdateText(text);
			}
		}

		private static void CompleteCurrentObjective()
		{
			if ((Object)(object)_currentObjective != (Object)null)
			{
				_currentObjective.Complete();
				_currentObjective = null;
			}
		}

		private static void DumpChain(CraftPlanner.RecipeChain chain, int repeatCount)
		{
			//IL_0079: Unknown result type (might be due to invalid IL or missing references)
			DebugLog.Trace(_log, "┌──────────────────────────────────────────────────────────┐");
			DebugLog.Trace(_log, $"│ CHAIN EXECUTION: {GetItemName(chain.ResultIndex)} (x{repeatCount})");
			DebugLog.Trace(_log, "├──────────────────────────────────────────────────────────┘");
			if (chain.DroneCostSparse.Length != 0)
			{
				DebugLog.Trace(_log, "│ [Resources] Drones Needed:");
				CraftPlanner.DroneRequirement[] droneCostSparse = chain.DroneCostSparse;
				for (int i = 0; i < droneCostSparse.Length; i++)
				{
					CraftPlanner.DroneRequirement droneRequirement = droneCostSparse[i];
					DebugLog.Trace(_log, "│   - " + GetDroneName(droneRequirement.DroneIdx) + " -> 1x " + GetItemName(droneRequirement.ScrapIndex));
				}
			}
			if (chain.AlliedTradeSparse.Length != 0)
			{
				DebugLog.Trace(_log, "│ [Resources] Allied Trades:");
				CraftPlanner.TradeRequirement[] alliedTradeSparse = chain.AlliedTradeSparse;
				for (int i = 0; i < alliedTradeSparse.Length; i++)
				{
					CraftPlanner.TradeRequirement tradeRequirement = alliedTradeSparse[i];
					DebugLog.Trace(_log, string.Format("│   - {0}: {1}x {2}", tradeRequirement.Donor?.userName ?? "Ally", tradeRequirement.Count, GetItemName(tradeRequirement.UnifiedIndex)));
				}
			}
			DebugLog.Trace(_log, "│ [Workflow] Sequence:");
			List<ChefRecipe> list = chain.Steps.Where((ChefRecipe s) => !(s is CraftPlanner.TradeRecipe)).ToList();
			for (int j = 0; j < list.Count; j++)
			{
				ChefRecipe chefRecipe = list[j];
				string text = string.Join(", ", chefRecipe.Ingredients.Select((Ingredient ing) => $"{ing.Count}x {GetItemName(ing.UnifiedIndex)}"));
				DebugLog.Trace(_log, $"│   Step {j + 1}: [{text}] —> {chefRecipe.ResultCount}x {GetItemName(chefRecipe.ResultIndex)}");
			}
			DebugLog.Trace(_log, "└──────────────────────────────────────────────────────────");
		}

		private static string GetItemName(int unifiedIndex)
		{
			if (unifiedIndex < ItemCatalog.itemCount)
			{
				return Language.GetString(ItemCatalog.GetItemDef((ItemIndex)unifiedIndex)?.nameToken ?? "Unknown Item");
			}
			return Language.GetString(EquipmentCatalog.GetEquipmentDef((EquipmentIndex)(unifiedIndex - ItemCatalog.itemCount))?.nameToken ?? "Unknown Equip");
		}
	}
	internal static class ObjectiveTracker
	{
		public class ObjectiveToken : ScriptableObject
		{
			private class CancelWatcher : MonoBehaviour
			{
				public ObjectiveToken TargetToken;

				private float _holdTimer;

				private const float THRESHOLD = 0.6f;

				private void Update()
				{
					//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)
					KeyboardShortcut value = CookBook.AbortKey.Value;
					if (((KeyboardShortcut)(ref value)).IsPressed())
					{
						_holdTimer += Time.deltaTime;
						if (_holdTimer >= 0.6f)
						{
							TargetToken.Complete();
						}
					}
					else
					{
						_holdTimer = 0f;
					}
				}
			}

			public string RawText;

			public uint SenderNetID;

			public int TrackedItemIdx;

			private GameObject _inputWatcher;

			public void Init(string text, uint senderID = 0u, int itemIdx = -1)
			{
				//IL_001b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Expected O, but got Unknown
				RawText = text;
				SenderNetID = senderID;
				TrackedItemIdx = itemIdx;
				_inputWatcher = new GameObject("CookBook_ObjectiveWatcher");
				_inputWatcher.AddComponent<CancelWatcher>().TargetToken = this;
			}

			public void UpdateText(string text)
			{
				RawText = text;
			}

			public void Complete()
			{
				if (Object.op_Implicit((Object)(object)_inputWatcher))
				{
					Object.Destroy((Object)(object)_inputWatcher);
				}
				RemoveToken(this);
				Object.Destroy((Object)(object)this);
			}
		}

		private class ChefObjectiveTracker : ObjectiveTracker
		{
			private ObjectiveToken MyToken => base.sourceDescriptor.source as ObjectiveToken;

			protected override bool IsDirty()
			{
				if ((Object)(object)MyToken != (Object)null)
				{
					return base.cachedString != ((ObjectiveTracker)this).GenerateString();
				}
				return false;
			}

			protected override string GenerateString()
			{
				//IL_0018: Unknown result type (might be due to invalid IL or missing references)
				//IL_001d: Unknown result type (might be due to invalid IL or missing references)
				//IL_0020: Unknown result type (might be due to invalid IL or missing references)
				//IL_0025: Unknown result type (might be due to invalid IL or missing references)
				if (!Object.op_Implicit((Object)(object)MyToken))
				{
					return string.Empty;
				}
				KeyboardShortcut value = CookBook.AbortKey.Value;
				KeyCode mainKey = ((KeyboardShortcut)(ref value)).MainKey;
				string text = ((object)(KeyCode)(ref mainKey)).ToString();
				return MyToken.RawText + " <style=cSub>[Hold " + text + " to Cancel]</style>";
			}
		}

		private static readonly List<ObjectiveToken> _activeObjectives = new List<ObjectiveToken>();

		internal static void Init()
		{
			ObjectivePanelController.collectObjectiveSources += OnCollectObjectiveSources;
		}

		internal static void Cleanup()
		{
			ObjectivePanelController.collectObjectiveSources -= OnCollectObjectiveSources;
			ClearAllObjectives();
		}

		internal static bool HasActiveObjectives()
		{
			return _activeObjectives.Count > 0;
		}

		internal static ObjectiveToken CreateObjective(string message, uint senderID = 0u, int itemIdx = -1)
		{
			ObjectiveToken objectiveToken = ScriptableObject.CreateInstance<ObjectiveToken>();
			objectiveToken.Init(message, senderID, itemIdx);
			_activeObjectives.Add(objectiveToken);
			return objectiveToken;
		}

		internal static void ClearSpecificRequest(uint senderID, int itemIdx)
		{
			for (int num = _activeObjectives.Count - 1; num >= 0; num--)
			{
				ObjectiveToken objectiveToken = _activeObjectives[num];
				if (objectiveToken.SenderNetID == senderID && objectiveToken.TrackedItemIdx == itemIdx)
				{
					objectiveToken.Complete();
				}
			}
		}

		internal static void ClearObjectivesFromSender(uint senderID)
		{
			for (int num = _activeObjectives.Count - 1; num >= 0; num--)
			{
				if (_activeObjectives[num].SenderNetID == senderID)
				{
					_activeObjectives[num].Complete();
				}
			}
		}

		internal static void AddAlliedRequest(NetworkUser sender, string command, int unifiedIdx, int quantity)
		{
			//IL_0083: Unknown result type (might be due to invalid IL or missing references)
			//IL_0088: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)sender == (Object)null))
			{
				string userName = sender.userName;
				string itemName = GetItemName(unifiedIdx);
				string text = string.Empty;
				if (command == "TRADE")
				{
					text = $"<style=cIsUtility>{userName} needs:</style> {quantity}x {itemName} <style=cStack>(Trade an Item)</style>";
				}
				else if (command == "SCRAP")
				{
					text = "<style=cIsUtility>" + userName + " needs:</style> " + itemName + " <style=cStack>(Scrap a Drone)</style>";
				}
				if (!string.IsNullOrEmpty(text))
				{
					string message = text;
					NetworkInstanceId netId = ((NetworkBehaviour)sender).netId;
					CreateObjective(message, ((NetworkInstanceId)(ref netId)).Value, unifiedIdx);
				}
			}
		}

		private static void RemoveToken(ObjectiveToken token)
		{
			if (_activeObjectives.Contains(token))
			{
				_activeObjectives.Remove(token);
			}
		}

		private static void OnCollectObjectiveSources(CharacterMaster viewerMaster, List<ObjectiveSourceDescriptor> output)
		{
			//IL_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0074: Unknown result type (might be due to invalid IL or missing references)
			LocalUser firstLocalUser = LocalUserManager.GetFirstLocalUser();
			if ((Object)(object)viewerMaster != (Object)(object)((firstLocalUser != null) ? firstLocalUser.cachedMaster : null))
			{
				return;
			}
			for (int num = _activeObjectives.Count - 1; num >= 0; num--)
			{
				ObjectiveToken objectiveToken = _activeObjectives[num];
				if (!Object.op_Implicit((Object)(object)objectiveToken))
				{
					_activeObjectives.RemoveAt(num);
				}
				else
				{
					output.Add(new ObjectiveSourceDescriptor
					{
						source = (Object)(object)objectiveToken,
						master = viewerMaster,
						objectiveType = typeof(ChefObjectiveTracker)
					});
				}
			}
		}

		internal static void ClearAllObjectives()
		{
			for (int num = _activeObjectives.Count - 1; num >= 0; num--)
			{
				if (Object.op_Implicit((Object)(object)_activeObjectives[num]))
				{
					_activeObjectives[num].Complete();
				}
			}
			_activeObjectives.Clear();
		}

		private static string GetItemName(int unifiedIdx)
		{
			int itemCount = ItemCatalog.itemCount;
			if (unifiedIdx < itemCount)
			{
				ItemDef itemDef = ItemCatalog.GetItemDef((ItemIndex)unifiedIdx);
				if (!Object.op_Implicit((Object)(object)itemDef))
				{
					return "Unknown Item";
				}
				return Language.GetString(itemDef.nameToken);
			}
			EquipmentDef equipmentDef = EquipmentCatalog.GetEquipmentDef((EquipmentIndex)(unifiedIdx - itemCount));
			if (!Object.op_Implicit((Object)(object)equipmentDef))
			{
				return "Unknown Equipment";
			}
			return Language.GetString(equipmentDef.nameToken);
		}
	}
	internal sealed class CraftPlanner
	{
		internal sealed class TradeRecipe : ChefRecipe
		{
			public NetworkUser Donor;

			public int ItemUnifiedIndex;

			public TradeRecipe(NetworkUser donor, int itemIndex)
				: base(itemIndex, 1, Array.Empty<Ingredient>())
			{
				Donor = donor;
				ItemUnifiedIndex = itemIndex;
			}

			public override int GetHashCode()
			{
				//IL_0006: 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)
				NetworkInstanceId netId = ((NetworkBehaviour)Donor).netId;
				return ((object)(NetworkInstanceId)(ref netId)).GetHashCode() * 31 + ItemUnifiedIndex;
			}
		}

		internal sealed class CraftableEntry
		{
			public int ResultIndex;

			public int ResultCount;

			public int MinDepth;

			public List<RecipeChain> Chains = new List<RecipeChain>();

			public bool IsItem => ResultIndex < ItemCatalog.itemCount;

			public ItemIndex ResultItem
			{
				get
				{
					if (IsItem)
					{
						return (ItemIndex)ResultIndex;
					}
					return (ItemIndex)(-1);
				}
			}

			public EquipmentIndex ResultEquipment
			{
				get
				{
					if (IsItem)
					{
						return (EquipmentIndex)(-1);
					}
					return (EquipmentIndex)(ResultIndex - ItemCatalog.itemCount);
				}
			}
		}

		internal struct TradeRequirement
		{
			public NetworkUser Donor;

			public int UnifiedIndex;

			public int Count;
		}

		internal sealed class RecipeChain
		{
			private readonly Dictionary<int, int> SurplusProfile;

			internal IReadOnlyList<ChefRecipe> Steps { get; }

			internal Ingredient[] PhysicalCostSparse { get; }

			internal DroneRequirement[] DroneCostSparse { get; }

			internal TradeRequirement[] AlliedTradeSparse { get; }

			internal int ResultIndex { get; }

			internal int ResultCount { get; }

			internal int ResultSurplus { get; }

			internal long CanonicalSignature { get; }

			internal int Depth => Steps.Count;

			public int GetNetSurplusFor(int itemIndex)
			{
				if (!SurplusProfile.TryGetValue(itemIndex, out var value))
				{
					return 0;
				}
				return value;
			}

			internal RecipeChain(ChefRecipe recipe, Ingredient[] phys, DroneRequirement[] drones, TradeRequirement[] trades, long sig)
			{
				Steps = new ChefRecipe[1] { recipe };
				ResultIndex = recipe.ResultIndex;
				ResultCount = recipe.ResultCount;
				ResultSurplus = recipe.ResultCount;
				PhysicalCostSparse = phys;
				DroneCostSparse = drones;
				AlliedTradeSparse = trades;
				CanonicalSignature = sig;
				SurplusProfile = new Dictionary<int, int> { { recipe.ResultIndex, recipe.ResultCount } };
				Ingredient[] ingredients = recipe.Ingredients;
				for (int i = 0; i < ingredients.Length; i++)
				{
					Ingredient ingredient = ingredients[i];
					SurplusProfile.TryGetValue(ingredient.UnifiedIndex, out var value);
					SurplusProfile[ingredient.UnifiedIndex] = value - ingredient.Count;
				}
			}

			internal RecipeChain(RecipeChain parent, ChefRecipe next, Ingredient[] phys, DroneRequirement[] drones, TradeRequirement[] trades, long sig)
			{
				Steps = parent.Steps.Append(next).ToArray();
				ResultIndex = next.ResultIndex;
				ResultCount = next.ResultCount;
				PhysicalCostSparse = phys;
				DroneCostSparse = drones;
				AlliedTradeSparse = trades;
				CanonicalSignature = sig;
				SurplusProfile = new Dictionary<int, int>(parent.SurplusProfile);
				SurplusProfile.TryGetValue(next.ResultIndex, out var value);
				SurplusProfile[next.ResultIndex] = value + next.ResultCount;
				Ingredient[] ingredients = next.Ingredients;
				for (int i = 0; i < ingredients.Length; i++)
				{
					Ingredient ingredient = ingredients[i];
					SurplusProfile.TryGetValue(ingredient.UnifiedIndex, out var value2);
					SurplusProfile[ingredient.UnifiedIndex] = value2 - ingredient.Count;
				}
				ResultSurplus = SurplusProfile[next.ResultIndex];
			}

			public int GetMaxAffordable(int[] localPhysical, int[] dronePotential, Dictionary<NetworkUser, int[]> alliedSnapshots, Dictionary<NetworkUser, int> remainingTrades)
			{
				int num = int.MaxValue;
				Ingredient[] physicalCostSparse = PhysicalCostSparse;
				for (int i = 0; i < physicalCostSparse.Length; i++)
				{
					Ingredient ingredient = physicalCostSparse[i];
					if (ingredient.Count != 0)
					{
						num = Math.Min(num, localPhysical[ingredient.UnifiedIndex] / ingredient.Count);
					}
				}
				Dictionary<int, int> dictionary = new Dictionary<int, int>();
				DroneRequirement[] droneCostSparse = DroneCostSparse;
				for (int i = 0; i < droneCostSparse.Length; i++)
				{
					DroneRequirement droneRequirement = droneCostSparse[i];
					if (droneRequirement.Count != 0)
					{
						if (!dictionary.ContainsKey(droneRequirement.ScrapIndex))
						{
							dictionary[droneRequirement.ScrapIndex] = 0;
						}
						dictionary[droneRequirement.ScrapIndex] += droneRequirement.Count;
					}
				}
				foreach (KeyValuePair<int, int> item in dictionary)
				{
					num = Math.Min(num, dronePotential[item.Key] / item.Value);
				}
				TradeRequirement[] alliedTradeSparse = AlliedTradeSparse;
				for (int i = 0; i < alliedTradeSparse.Length; i++)
				{
					TradeRequirement tradeRequirement = alliedTradeSparse[i];
					if (tradeRequirement.Count != 0)
					{
						if (!alliedSnapshots.TryGetValue(tradeRequirement.Donor, out var value))
						{
							return 0;
						}
						if (!remainingTrades.TryGetValue(tradeRequirement.Donor, out var value2))
						{
							return 0;
						}
						num = Math.Min(num, Math.Min(value[tradeRequirement.UnifiedIndex] / tradeRequirement.Count, value2 / tradeRequirement.Count));
					}
				}
				if (num != int.MaxValue)
				{
					return num;
				}
				return 0;
			}

			internal static long CalculateCanonicalSignature(IEnumerable<ChefRecipe> chain)
			{
				if (chain == null)
				{
					return 0L;
				}
				long num = 0L;
				foreach (ChefRecipe item in chain)
				{
					num += item.GetHashCode();
				}
				return num;
			}

			internal static long CalculateRollingSignature(long currentSignature, ChefRecipe next)
			{
				return currentSignature + next.GetHashCode();
			}
		}

		internal struct DroneRequirement
		{
			public NetworkUser Owner;

			public DroneIndex DroneIdx;

			public int Count;

			public int TotalUpgradeCount;

			public int ScrapIndex;
		}

		private readonly ManualLogSource _log;

		private int _maxDepth;

		private readonly int _itemCount;

		private readonly int _totalDefCount;

		private readonly HashSet<int> _dirtyIndices = new HashSet<int>();

		private readonly HashSet<int> _allIngredientIndices = new HashSet<int>();

		private readonly HashSet<int> _transientIngredients = new HashSet<int>();

		private HashSet<ItemIndex> _lastKnownCorrupted = new HashSet<ItemIndex>();

		private readonly int[] _maxDemand;

		private readonly int[] _needsBuffer;

		private readonly int[] _productionBuffer;

		private readonly List<Ingredient> _tempPhysList = new List<Ingredient>();

		private readonly List<DroneRequirement> _tempDroneReqList = new List<DroneRequirement>();

		private readonly IReadOnlyList<ChefRecipe> _recipes;

		private Dictionary<int, CraftableEntry> _entryCache = new Dictionary<int, CraftableEntry>();

		public int SourceItemCount { get; }

		internal event Action<List<CraftableEntry>> OnCraftablesUpdated;

		public CraftPlanner(IReadOnlyList<ChefRecipe> recipes, int maxDepth, ManualLogSource log)
		{
			_recipes = recipes?.Distinct().ToList() ?? throw new ArgumentNullException("recipes");
			_maxDepth = maxDepth;
			_itemCount = ItemCatalog.itemCount;
			_totalDefCount = _itemCount + EquipmentCatalog.equipmentCount;
			_log = log;
			SourceItemCount = ItemCatalog.itemCount;
			int num = _totalDefCount + 10;
			_maxDemand = new int[num];
			_needsBuffer = new int[num];
			_productionBuffer = new int[num];
			BuildRecipeIndex();
		}

		internal void SetMaxDepth(int newDepth)
		{
			_maxDepth = Math.Max(0, newDepth);
		}

		private void BuildRecipeIndex()
		{
			_allIngredientIndices.Clear();
			Array.Clear(_maxDemand, 0, _maxDemand.Length);
			DebugLog.Trace(_log, $"[Planner] Building Demand Index for {_recipes.Count} recipes...");
			foreach (ChefRecipe recipe in _recipes)
			{
				Ingredient[] ingredients = recipe.Ingredients;
				for (int i = 0; i < ingredients.Length; i++)
				{
					Ingredient ingredient = ingredients[i];
					int unifiedIndex = ingredient.UnifiedIndex;
					_allIngredientIndices.Add(unifiedIndex);
					if (ingredient.Count > _maxDemand[unifiedIndex])
					{
						_maxDemand[unifiedIndex] = ingredient.Count;
					}
				}
			}
		}

		public void ComputeCraftable(int[] unifiedStacks, IReadOnlyList<ChefRecipe> recipes, bool canScrapDrones, HashSet<int> changedIndices = null, bool forceUpdate = false)
		{
			if (!StateController.IsChefStage() || unifiedStacks == null)
			{
				return;
			}
			if (!forceUpdate && changedIndices != null && changedIndices.Count > 0 && _entryCache.Count > 0)
			{
				bool flag = false;
				foreach (int changedIndex in changedIndices)
				{
					if (_allIngredientIndices.Contains(changedIndex) || _entryCache.ContainsKey(changedIndex))
					{
						flag = true;
						break;
					}
					if (IsTransformedItemRelevant(changedIndex))
					{
						flag = true;
						break;
					}
				}
				if (!flag)
				{
					RefreshVisualOverridesAndEmit();
					return;
				}
			}
			Stopwatch stopwatch = Stopwatch.StartNew();
			_transientIngredients.Clear();
			foreach (ChefRecipe recipe in recipes)
			{
				Ingredient[] ingredients = recipe.Ingredients;
				for (int i = 0; i < ingredients.Length; i++)
				{
					Ingredient ingredient = ingredients[i];
					_transientIngredients.Add(ingredient.UnifiedIndex);
				}
			}
			Dictionary<int, List<RecipeChain>> dictionary = new Dictionary<int, List<RecipeChain>>();
			HashSet<long> hashSet = new HashSet<long>();
			Queue<RecipeChain> queue = new Queue<RecipeChain>();
			foreach (ChefRecipe recipe2 in recipes)
			{
				if (!isRecipeAffordable(unifiedStacks, recipe2, canScrapDrones, null))
				{
					continue;
				}
				var (array, drones, trades) = CalculateSplitCosts(null, recipe2, canScrapDrones, unifiedStacks);
				if (array != null)
				{
					long sig = recipe2.GetHashCode();
					RecipeChain recipeChain = new RecipeChain(recipe2, array, drones, trades, sig);
					if (hashSet.Add(recipeChain.CanonicalSignature))
					{
						AddChainToResults(dictionary, queue, recipeChain);
					}
				}
			}
			if (CookBook.IsPoolingEnabled)
			{
				InjectTradeRecipes(null, dictionary, queue, hashSet, _transientIngredients);
			}
			for (int j = 2; j <= _maxDepth; j++)
			{
				int count = queue.Count;
				if (count == 0)
				{
					break;
				}
				for (int k = 0; k < count; k++)
				{
					RecipeChain recipeChain2 = queue.Dequeue();
					foreach (ChefRecipe recipe3 in recipes)
					{
						if (!IsCausallyLinked(recipeChain2, recipe3))
						{
							continue;
						}
						long num = RecipeChain.CalculateRollingSignature(recipeChain2.CanonicalSignature, recipe3);
						if (hashSet.Add(num) && isRecipeAffordable(unifiedStacks, recipe3, canScrapDrones, recipeChain2))
						{
							var (array2, drones2, trades2) = CalculateSplitCosts(recipeChain2, recipe3, canScrapDrones, unifiedStacks);
							if (array2 != null)
							{
								recipeChain2.Steps.Concat(new ChefRecipe[1] { recipe3 }).ToList();
								RecipeChain chain = new RecipeChain(recipeChain2, recipe3, array2, drones2, trades2, num);
								AddChainToResults(dictionary, queue, chain);
							}
						}
					}
				}
			}
			_entryCache = (from e in dictionary.Select(delegate(KeyValuePair<int, List<RecipeChain>> kvp)
				{
					List<RecipeChain> list2 = (from c in kvp.Value
						where c.ResultIndex == kvp.Key
						where c.Steps.Count != 1 || !(c.Steps[0] is TradeRecipe)
						where c.ResultSurplus == c.ResultCount
						orderby c.DroneCostSparse.Length, c.Depth
						select c).ToList();
					return (list2.Count == 0) ? null : new CraftableEntry
					{
						ResultIndex = kvp.Key,
						ResultCount = list2[0].ResultCount,
						MinDepth = list2[0].Depth,
						Chains = list2
					};
				})
				where e != null
				select e).ToDictionary((CraftableEntry e) => e.ResultIndex);
			List<CraftableEntry> list = _entryCache.Values.ToList();
			RefreshVisualOverridesAndEmit();
			list.Sort(TierManager.CompareCraftableEntries);
			stopwatch.Stop();
			DebugLog.Trace(_log, $"[Planner] Rebuild complete: {stopwatch.ElapsedMilliseconds}ms for {list.Count} entries.");
		}

		private string GetChainSummary(RecipeChain chain)
		{
			string text = string.Join(" -> ", chain.Steps.Select((ChefRecipe s) => (!(s is TradeRecipe tradeRecipe)) ? GetItemName(s.ResultIndex) : ("Trade(" + GetItemName(tradeRecipe.ItemUnifiedIndex) + ")")));
			int weightedCost = GetWeightedCost(chain);
			int resultSurplus = chain.ResultSurplus;
			return $"[Depth {chain.Depth}, Weight {weightedCost}, Surplus {resultSurplus}] {text}";
		}

		private string GetItemName(int unifiedIndex)
		{
			if (unifiedIndex < ItemCatalog.itemCount)
			{
				return Language.GetString(ItemCatalog.GetItemDef((ItemIndex)unifiedIndex)?.nameToken ?? "Unknown Item");
			}
			return Language.GetString(EquipmentCatalog.GetEquipmentDef((EquipmentIndex)(unifiedIndex - ItemCatalog.itemCount))?.nameToken ?? "Unknown Equip");
		}

		private bool IsCausallyLinked(RecipeChain chain, ChefRecipe next)
		{
			Ingredient[] ingredients = next.Ingredients;
			for (int i = 0; i < ingredients.Length; i++)
			{
				Ingredient ingredient = ingredients[i];
				if (chain.GetNetSurplusFor(ingredient.UnifiedIndex) > 0)
				{
					return true;
				}
			}
			int resultIndex = next.ResultIndex;
			int num = _maxDemand[resultIndex];
			if (num > 1)
			{
				int netSurplusFor = chain.GetNetSurplusFor(resultIndex);
				if (netSurplusFor > 0 && netSurplusFor < num)
				{
					return true;
				}
			}
			return false;
		}

		private bool IsChainInefficient(RecipeChain chain)
		{
			int weightedCost = GetWeightedCost(chain);
			int num = chain.ResultSurplus * GetItemWeight(chain.ResultIndex);
			return weightedCost > num * 2;
		}

		private bool IsChainDominated(RecipeChain newChain, Dictionary<int, List<RecipeChain>> discovered)
		{
			if (!discovered.TryGetValue(newChain.ResultIndex, out var value))
			{
				return false;
			}
			int weightedCost = GetWeightedCost(newChain);
			foreach (RecipeChain item in value)
			{
				int weightedCost2 = GetWeightedCost(item);
				if (item.Depth < newChain.Depth && weightedCost2 <= weightedCost && HasSuperiorSurplusProfile(item, newChain))
				{
					return true;
				}
			}
			return false;
		}

		private bool isRecipeAffordable(int[] totalStacks, ChefRecipe recipe, bool scrapperPresent, RecipeChain existingChain)
		{
			Ingredient[] ingredients = recipe.Ingredients;
			for (int i = 0; i < ingredients.Length; i++)
			{
				Ingredient ingredient = ingredients[i];
				int unifiedIndex = ingredient.UnifiedIndex;
				int num = existingChain?.GetNetSurplusFor(unifiedIndex) ?? 0;
				int num2 = Math.Max(0, ingredient.Count - num);
				if (num2 > 0)
				{
					int num3 = totalStacks[unifiedIndex];
					int num4 = (scrapperPresent ? InventoryTracker.GetGlobalDronePotentialCount(unifiedIndex) : 0);
					if (num3 + num4 < num2)
					{
						return false;
					}
				}
			}
			return true;
		}

		private void InjectTradeRecipes(RecipeChain chain, Dictionary<int, List<RecipeChain>> discovered, Queue<RecipeChain> queue, HashSet<long> signatures, HashSet<int> validIngredients)
		{
			Dictionary<NetworkUser, int[]> alliedS