Decompiled source of NoLazyWorkers v1.1.10

Mods/NoLazyWorkers.dll

Decompiled 2 months ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using FishNet;
using FishNet.Connection;
using FishNet.Object;
using HarmonyLib;
using MelonLoader;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using NoLazyWorkers;
using NoLazyWorkers.Botanists;
using NoLazyWorkers.Chemists;
using NoLazyWorkers.Settings;
using ScheduleOne.DevUtilities;
using ScheduleOne.Employees;
using ScheduleOne.EntityFramework;
using ScheduleOne.ItemFramework;
using ScheduleOne.Management;
using ScheduleOne.Management.Presets;
using ScheduleOne.Management.Presets.Options;
using ScheduleOne.Management.SetterScreens;
using ScheduleOne.Management.UI;
using ScheduleOne.NPCs;
using ScheduleOne.NPCs.Behaviour;
using ScheduleOne.ObjectScripts;
using ScheduleOne.Persistence;
using ScheduleOne.Persistence.Datas;
using ScheduleOne.Persistence.Loaders;
using ScheduleOne.Product;
using ScheduleOne.Quests;
using ScheduleOne.Tiles;
using ScheduleOne.UI.Management;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(NoLazyWorkersMod), "NoLazyWorkers", "1.1.10", "Archie", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: HarmonyDontPatchAll]
[assembly: TargetFramework(".NETFramework,Version=v4.8.1", FrameworkDisplayName = ".NET Framework 4.8.1")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: AssemblyCompany("NoLazyWorkers")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+d2bb5a695973e93b9a87bc9642a928386d6f5b68")]
[assembly: AssemblyProduct("NoLazyWorkers")]
[assembly: AssemblyTitle("NoLazyWorkers")]
[assembly: NeutralResourcesLanguage("en-US")]
[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;
		}
	}
}
namespace NoLazyWorkers
{
	public static class DebugLogs
	{
		public static bool All;

		public static bool Core;

		public static bool Settings;

		public static bool Pot;

		public static bool MixingStation;

		public static bool Storage;

		public static bool Chemist;

		public static bool Botanist;

		public static bool Packager;

		public static bool Stacktrace;
	}
	public static class BuildInfo
	{
		public const string Name = "NoLazyWorkers";

		public const string Description = "Botanist's supply is moved to each pot and a supply is added to mixing stations. Botanists and Chemists will get items from their station's supply. Mixing Stations can have multiple recipes that loop the output. Multiple employee-related configurable settings.";

		public const string Author = "Archie";

		public const string Version = "1.1.10";
	}
	public class NoLazyWorkersMod : MelonMod
	{
		public static NoLazyWorkersMod Instance { get; private set; }

		public Default Config { get; private set; }

		public override void OnInitializeMelon()
		{
			try
			{
				((MelonBase)this).HarmonyInstance.PatchAll();
				MelonLogger.Msg("NoLazyWorkers_Alternative loaded!");
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"Failed to initialize NoLazyWorkers_Alternative: {arg}");
			}
			Instance = this;
			string text = Path.Combine(MelonEnvironment.UserDataDirectory, "NoLazyWorkers.cfg");
			if (File.Exists(text))
			{
				Config = Default.LoadFromFile(text);
				if (DebugLogs.All || DebugLogs.Core)
				{
					MelonLogger.Msg("Config loaded.");
				}
			}
			else
			{
				Config = new Default();
				Config.SaveToFile(text);
				if (DebugLogs.All || DebugLogs.Core)
				{
					MelonLogger.Msg("Default config created.");
				}
			}
			((MelonEventBase<LemonAction<int, string>>)(object)MelonEvents.OnSceneWasLoaded).Subscribe((LemonAction<int, string>)((MelonMod)this).OnSceneWasLoaded, 0, false);
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			if (sceneName == "Main")
			{
				Configure configure = new Configure();
				MelonCoroutines.Start(configure.ApplyOneShotSettingsRoutine());
				if (DebugLogs.All || DebugLogs.Core)
				{
					MelonLogger.Msg("Applied Fixer and Misc settings on main scene load.");
				}
				MixingStationExtensions.InitializeStaticRouteListTemplate();
			}
		}

		public override void OnSceneWasUnloaded(int buildIndex, string sceneName)
		{
			ConfigurationExtensions.NPCSupply.Clear();
			SettingsExtensions.Configured.Clear();
			if (DebugLogs.All || DebugLogs.Core)
			{
				MelonLogger.Msg("Cleared ConfigurationExtensions and SettingsExtensions on scene unload.");
			}
		}
	}
	public static class ConfigurationExtensions
	{
		public static Dictionary<Guid, ObjectField> NPCSupply = new Dictionary<Guid, ObjectField>();

		private static readonly Dictionary<EntityConfiguration, float> lastInvokeTimes = new Dictionary<EntityConfiguration, float>();

		private static readonly float debounceTime = 0.2f;

		public static void InvokeChanged(EntityConfiguration config)
		{
			try
			{
				if (config == null)
				{
					MelonLogger.Error("InvokeChanged: EntityConfiguration is null");
					return;
				}
				float time = Time.time;
				if (lastInvokeTimes.TryGetValue(config, out var value) && time - value < debounceTime)
				{
					if (DebugLogs.All || DebugLogs.Core)
					{
						MelonLogger.Msg($"InvokeChanged debounced for config: {config}");
					}
					return;
				}
				lastInvokeTimes[config] = time;
				if (DebugLogs.Stacktrace)
				{
					MelonLogger.Msg($"InvokeChanged called for config: {config}, StackTrace: {new StackTrace()}");
				}
				config.InvokeChanged();
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"InvokeChanged failed: {arg}");
			}
		}
	}
	public static class NoLazyUtilities
	{
		public class CoroutineRunner : MonoBehaviour
		{
			[CompilerGenerated]
			private sealed class <RunCoroutineInternal>d__4<T> : IEnumerator<object>, IDisposable, IEnumerator
			{
				private int <>1__state;

				private object <>2__current;

				public IEnumerator coroutine;

				public Action<T> callback;

				public CoroutineRunner <>4__this;

				private object <current>5__1;

				private T <result>5__2;

				private Exception <e>5__3;

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

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

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

				[DebuggerHidden]
				void IDisposable.Dispose()
				{
					<current>5__1 = null;
					<result>5__2 = default(T);
					<e>5__3 = null;
					<>1__state = -2;
				}

				private bool MoveNext()
				{
					switch (<>1__state)
					{
					default:
						return false;
					case 0:
						<>1__state = -1;
						break;
					case 1:
						<>1__state = -1;
						<current>5__1 = null;
						<result>5__2 = default(T);
						break;
					}
					try
					{
						if (!coroutine.MoveNext())
						{
							return false;
						}
						<current>5__1 = coroutine.Current;
					}
					catch (Exception ex)
					{
						<e>5__3 = ex;
						MelonLogger.Error("CoroutineRunner: Exception in coroutine: " + <e>5__3.Message + ", stack: " + <e>5__3.StackTrace);
						callback?.Invoke(default(T));
						return false;
					}
					if (<current>5__1 is T)
					{
						<result>5__2 = (T)<current>5__1;
						if (true)
						{
							callback?.Invoke(<result>5__2);
							return false;
						}
					}
					<>2__current = <current>5__1;
					<>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 CoroutineRunner _instance;

			public static CoroutineRunner Instance
			{
				get
				{
					//IL_0016: Unknown result type (might be due to invalid IL or missing references)
					//IL_001c: Expected O, but got Unknown
					if ((Object)(object)_instance == (Object)null)
					{
						GameObject val = new GameObject("CoroutineRunner");
						_instance = val.AddComponent<CoroutineRunner>();
						Object.DontDestroyOnLoad((Object)(object)val);
					}
					return _instance;
				}
			}

			public void RunCoroutineWithResult<T>(IEnumerator coroutine, Action<T> callback)
			{
				((MonoBehaviour)this).StartCoroutine(RunCoroutineInternal(coroutine, callback));
			}

			[IteratorStateMachine(typeof(<RunCoroutineInternal>d__4<>))]
			private IEnumerator RunCoroutineInternal<T>(IEnumerator coroutine, Action<T> callback)
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <RunCoroutineInternal>d__4<T>(0)
				{
					<>4__this = this,
					coroutine = coroutine,
					callback = callback
				};
			}
		}

		public static int GetAmountInInventoryAndSupply(NPC npc, ItemDefinition item)
		{
			if ((Object)(object)npc == (Object)null || (Object)(object)item == (Object)null)
			{
				if (DebugLogs.All || DebugLogs.Core || DebugLogs.Chemist || DebugLogs.Botanist)
				{
					MelonLogger.Warning("GetAmountInInventoryAndSupply: NPC or item is null");
				}
				return 0;
			}
			NPCInventory inventory = npc.Inventory;
			int num = ((inventory != null) ? inventory._GetItemAmount(item.ID) : 0);
			int amountInSupply = GetAmountInSupply(npc, item.GetDefaultInstance(1));
			return num + amountInSupply;
		}

		public static int GetAmountInSupply(NPC npc, ItemInstance item)
		{
			if ((Object)(object)npc == (Object)null || item == null || string.IsNullOrEmpty(item.ID))
			{
				if (DebugLogs.All || DebugLogs.Core || DebugLogs.Chemist || DebugLogs.Botanist)
				{
					MelonLogger.Warning(string.Format("GetAmountInSupplies: NPC={0}, item={1}, or item.ID={2} is null for {3}", npc, item, item?.ID, ((npc != null) ? npc.fullName : null) ?? "null"));
				}
				return 0;
			}
			if (!ConfigurationExtensions.NPCSupply.TryGetValue(npc.GUID, out var value) || (Object)(object)value?.SelectedObject == (Object)null)
			{
				if (DebugLogs.All || DebugLogs.Core || DebugLogs.Chemist || DebugLogs.Botanist)
				{
					MelonLogger.Warning("GetAmountInSupplies: Supply or SelectedObject is null for " + npc.fullName);
				}
				return 0;
			}
			BuildableItem selectedObject = value.SelectedObject;
			ITransitEntity val = (ITransitEntity)(object)((selectedObject is ITransitEntity) ? selectedObject : null);
			if (val == null)
			{
				if (DebugLogs.All || DebugLogs.Core || DebugLogs.Chemist || DebugLogs.Botanist)
				{
					MelonLogger.Warning("GetAmountInSupplies: Supply is not ITransitEntity for " + npc.fullName);
				}
				return 0;
			}
			if (!npc.Movement.CanGetTo(val, 1f))
			{
				if (DebugLogs.All || DebugLogs.Core || DebugLogs.Chemist || DebugLogs.Botanist)
				{
					MelonLogger.Warning("GetAmountInSupplies: Cannot reach supply for " + npc.fullName);
				}
				return 0;
			}
			IEnumerable<ItemSlot> enumerable = (from s in (val.OutputSlots ?? new List<ItemSlot>()).Concat(val.InputSlots ?? new List<ItemSlot>())
				where ((s != null) ? s.ItemInstance : null) != null && s.Quantity > 0
				select s).Distinct();
			if (!enumerable.Any())
			{
				if (DebugLogs.All || DebugLogs.Core || DebugLogs.Chemist || DebugLogs.Botanist)
				{
					MelonLogger.Warning("GetAmountInSupplies: No valid slots in supply " + ((val != null) ? val.Name : null) + " for " + npc.fullName);
				}
				return 0;
			}
			int num = 0;
			string text = item.ID.ToLower();
			foreach (ItemSlot item2 in enumerable)
			{
				if (item2.ItemInstance.ID.ToLower() == text)
				{
					num += item2.Quantity;
					if (DebugLogs.All || DebugLogs.Core || DebugLogs.Chemist || DebugLogs.Botanist)
					{
						MelonLogger.Msg($"GetAmountInSupplies: Found {text} with quantity={item2.Quantity} in slot {((object)item2).GetHashCode()} for {npc.fullName}");
					}
				}
				else if (DebugLogs.All || DebugLogs.Core || DebugLogs.Chemist || DebugLogs.Botanist)
				{
					MelonLogger.Msg($"GetAmountInSupplies: Slot {((object)item2).GetHashCode()} contains {item2.ItemInstance.ID} (quantity={item2.Quantity}), not {text} for {npc.fullName}");
				}
			}
			if (num == 0)
			{
				if (DebugLogs.All || DebugLogs.Core || DebugLogs.Chemist || DebugLogs.Botanist)
				{
					MelonLogger.Msg("GetAmountInSupplies: No items of " + item.ID + " found in supply " + ((val != null) ? val.Name : null) + " for " + npc.fullName);
				}
			}
			else if (DebugLogs.All || DebugLogs.Core || DebugLogs.Chemist || DebugLogs.Botanist)
			{
				MelonLogger.Msg($"GetAmountInSupplies: Total quantity of {item.ID} is {num} in supply {((val != null) ? val.Name : null)} for {npc.fullName}");
			}
			return num;
		}

		public static Transform GetTransformTemplateFromConfigPanel(EConfigurableType configType, string componentStr)
		{
			//IL_0200: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: 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)
			//IL_0018: Expected O, but got Unknown
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0022: Expected O, but got Unknown
			//IL_0022: 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_0025: 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_0029: Unknown result type (might be due to invalid IL or missing references)
			//IL_004b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0051: Expected O, but got Unknown
			//IL_002f: Unknown result type (might be due to invalid IL or missing references)
			//IL_0032: Invalid comparison between Unknown and I4
			//IL_00d6: 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_0071: Expected O, but got Unknown
			//IL_011d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0036: Unknown result type (might be due to invalid IL or missing references)
			//IL_003a: Invalid comparison between Unknown and I4
			//IL_008b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0091: Expected O, but got Unknown
			//IL_00a3: Unknown result type (might be due to invalid IL or missing references)
			//IL_0172: Unknown result type (might be due to invalid IL or missing references)
			//IL_01a5: Unknown result type (might be due to invalid IL or missing references)
			//IL_01d2: Unknown result type (might be due to invalid IL or missing references)
			try
			{
				GameObject val = new GameObject($"Dummy{configType}");
				EntityConfiguration val2 = null;
				GameObject val3 = null;
				ConfigurationReplicator val4 = new ConfigurationReplicator();
				if ((int)configType != 0)
				{
					if ((int)configType != 4)
					{
						if ((int)configType != 10)
						{
							MelonLogger.Error($"Unsupported EConfigurableType: {configType}");
							Object.Destroy((Object)(object)val);
							return null;
						}
						MixingStation val5 = val.AddComponent<MixingStation>();
						val2 = (EntityConfiguration)new MixingStationConfiguration(val4, (IConfigurable)(object)val5, val5);
						val3 = GetPrefabGameObject("MixingStationPanel");
					}
					else
					{
						Packager val6 = val.AddComponent<Packager>();
						val2 = (EntityConfiguration)new PackagerConfiguration(val4, (IConfigurable)(object)val6, val6);
						val3 = GetPrefabGameObject("PackagerConfigPanel");
					}
				}
				else
				{
					Pot val7 = val.AddComponent<Pot>();
					val2 = (EntityConfiguration)new PotConfiguration(val4, (IConfigurable)(object)val7, val7);
					val3 = GetPrefabGameObject("PotConfigPanel");
				}
				if ((Object)(object)val3 == (Object)null)
				{
					MelonLogger.Error($"No ConfigPanel prefab found for {configType}");
					return null;
				}
				GameObject val8 = Object.Instantiate<GameObject>(val3);
				val8.SetActive(false);
				ConfigPanel component = val8.GetComponent<ConfigPanel>();
				if ((Object)(object)component == (Object)null)
				{
					MelonLogger.Error($"Instantiated prefab for {configType} lacks ConfigPanel component");
					Object.Destroy((Object)(object)val8);
					return null;
				}
				List<EntityConfiguration> list = new List<EntityConfiguration>();
				list.Add(val2);
				component.Bind(list);
				if (DebugLogs.All || DebugLogs.Core)
				{
					MelonLogger.Msg($"Bound temporary ConfigPanel for {configType} to initialize UI components");
				}
				Transform val9 = ((Component)component).transform.Find(componentStr);
				if ((Object)(object)val9 == (Object)null)
				{
					MelonLogger.Error($"Failed to retrieve UI template from ConfigPanel for {configType}");
				}
				else if (DebugLogs.All || DebugLogs.Core)
				{
					MelonLogger.Msg($"Successfully retrieved UI template from ConfigPanel for {configType}");
				}
				Object.Destroy((Object)(object)val8);
				Object.Destroy((Object)(object)val);
				return val9;
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"Failed to get UI template from ConfigPanel for {configType}: {arg}");
				return null;
			}
		}

		public static GameObject GetPrefabGameObject(string id)
		{
			try
			{
				GameObject val = null;
				GameObject[] array = Resources.FindObjectsOfTypeAll<GameObject>();
				GameObject[] array2 = array;
				foreach (GameObject val2 in array2)
				{
					if (((Object)val2).name.Contains(id))
					{
						if (DebugLogs.All || DebugLogs.Core)
						{
							MelonLogger.Msg("Found prefab: " + ((Object)val2).name);
						}
						val = val2;
						break;
					}
				}
				if ((Object)(object)val != (Object)null)
				{
					GameObject val3 = Object.Instantiate<GameObject>(val);
					if (DebugLogs.All || DebugLogs.Core)
					{
						MelonLogger.Msg("Instantiated prefab: " + ((Object)val3).name);
					}
					return val3;
				}
				MelonLogger.Error("Prefab " + id + " not found in Resources.");
				return null;
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"Failed to find prefab: {arg}");
				return null;
			}
		}

		public static void LogItemFieldUIDetails(ItemFieldUI itemfieldUI)
		{
			if (DebugLogs.All || DebugLogs.Core)
			{
				MelonLogger.Msg("=== ItemFieldUI Details ===");
			}
			if (DebugLogs.All || DebugLogs.Core)
			{
				MelonLogger.Msg("ItemFieldUI GameObject: " + (((Object)(object)((Component)itemfieldUI).gameObject != (Object)null) ? ((Object)((Component)itemfieldUI).gameObject).name : "null"));
			}
			if (DebugLogs.All || DebugLogs.Core)
			{
				GameObject gameObject = ((Component)itemfieldUI).gameObject;
				MelonLogger.Msg($"ItemFieldUI Active: {((gameObject != null) ? new bool?(gameObject.activeSelf) : null)}");
			}
			if (DebugLogs.All || DebugLogs.Core)
			{
				MelonLogger.Msg("ItemFieldUI Type: " + ((object)itemfieldUI).GetType().Name);
			}
			LogComponentDetails((Component)(object)itemfieldUI, 0);
			if (DebugLogs.All || DebugLogs.Core)
			{
				MelonLogger.Msg("--- Hierarchy and Components ---");
			}
			if ((Object)(object)((Component)itemfieldUI).gameObject != (Object)null)
			{
				LogGameObjectDetails(((Component)itemfieldUI).gameObject, 0);
			}
			else if (DebugLogs.All || DebugLogs.Core)
			{
				MelonLogger.Warning("ItemFieldUI GameObject is null, cannot log hierarchy and components");
			}
		}

		private static void LogGameObjectDetails(GameObject go, int indentLevel)
		{
			//IL_00ca: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d1: Expected O, but got Unknown
			if ((Object)(object)go == (Object)null)
			{
				if (DebugLogs.All || DebugLogs.Core)
				{
					MelonLogger.Msg(new string(' ', indentLevel * 2) + "GameObject: null");
				}
				return;
			}
			if (DebugLogs.All || DebugLogs.Core)
			{
				MelonLogger.Msg(new string(' ', indentLevel * 2) + $"GameObject: {((Object)go).name}, Active: {go.activeSelf}");
			}
			Component[] components = go.GetComponents<Component>();
			foreach (Component component in components)
			{
				LogComponentDetails(component, indentLevel + 1);
			}
			foreach (Transform item in go.transform)
			{
				Transform val = item;
				LogGameObjectDetails(((Component)val).gameObject, indentLevel + 1);
			}
		}

		private static void LogComponentDetails(Component component, int indentLevel)
		{
			if ((Object)(object)component == (Object)null)
			{
				if (DebugLogs.All || DebugLogs.Core)
				{
					MelonLogger.Msg(new string(' ', indentLevel * 2) + "Component: null");
				}
				return;
			}
			if (DebugLogs.All || DebugLogs.Core)
			{
				MelonLogger.Msg(new string(' ', indentLevel * 2) + "Component: " + ((object)component).GetType().Name);
			}
			FieldInfo[] fields = ((object)component).GetType().GetFields(BindingFlags.Instance | BindingFlags.Public);
			FieldInfo[] array = fields;
			foreach (FieldInfo fieldInfo in array)
			{
				try
				{
					object value = fieldInfo.GetValue(component);
					string text = ValueToString(value);
					if (DebugLogs.All || DebugLogs.Core)
					{
						MelonLogger.Msg(new string(' ', indentLevel * 2) + "  Field: " + fieldInfo.Name + " = " + text);
					}
				}
				catch (Exception ex)
				{
					MelonLogger.Error(new string(' ', indentLevel * 2) + "  Failed to get field " + fieldInfo.Name + ": " + ex.Message);
				}
			}
			PropertyInfo[] properties = ((object)component).GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public);
			PropertyInfo[] array2 = properties;
			foreach (PropertyInfo propertyInfo in array2)
			{
				if (!propertyInfo.CanRead)
				{
					continue;
				}
				try
				{
					object value2 = propertyInfo.GetValue(component);
					string text2 = ValueToString(value2);
					if (DebugLogs.All || DebugLogs.Core)
					{
						MelonLogger.Msg(new string(' ', indentLevel * 2) + "  Property: " + propertyInfo.Name + " = " + text2);
					}
				}
				catch (Exception ex2)
				{
					MelonLogger.Error(new string(' ', indentLevel * 2) + "  Failed to get property " + propertyInfo.Name + ": " + ex2.Message);
				}
			}
		}

		private static string ValueToString(object value)
		{
			if (value == null)
			{
				return "null";
			}
			GameObject val = (GameObject)((value is GameObject) ? value : null);
			if (val != null)
			{
				return "GameObject(" + ((Object)val).name + ")";
			}
			Component val2 = (Component)((value is Component) ? value : null);
			if (val2 != null)
			{
				return ((object)val2).GetType().Name + " on " + ((Object)val2.gameObject).name;
			}
			if (value is IEnumerable enumerable && !(value is string))
			{
				List<string> list = new List<string>();
				foreach (object item in enumerable)
				{
					list.Add(ValueToString(item));
				}
				return "[" + string.Join(", ", list) + "]";
			}
			return value.ToString();
		}
	}
	[HarmonyPatch(typeof(ItemSetterScreen), "Open")]
	public class ItemSetterScreenOpenPatch
	{
		private static void Prefix(ItemSetterScreen __instance, object option)
		{
			try
			{
				ItemField val = (ItemField)((option is ItemField) ? option : null);
				if (val != null)
				{
					if (DebugLogs.All || DebugLogs.Core)
					{
						MelonLogger.Msg("ItemSetterScreenOpenPatch: Opening for ItemField, SelectedItem: " + (val.SelectedItem?.Name ?? "null"));
					}
					if (val.Options != null)
					{
						if (DebugLogs.All || DebugLogs.Core)
						{
							MelonLogger.Msg($"ItemSetterScreenOpenPatch: ItemField options count: {val.Options.Count}");
						}
					}
					else if (DebugLogs.All || DebugLogs.Core)
					{
						MelonLogger.Warning("ItemSetterScreenOpenPatch: ItemField Options is null");
					}
				}
				else if (DebugLogs.All || DebugLogs.Core)
				{
					MelonLogger.Msg("ItemSetterScreenOpenPatch: Opening for " + (option?.GetType().Name ?? "null"));
				}
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"ItemSetterScreenOpenPatch: Prefix failed, error: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(EntityConfiguration), "Selected")]
	public class EntityConfigurationSelectedPatch
	{
		private static void Postfix(EntityConfiguration __instance)
		{
			try
			{
				if (DebugLogs.All || DebugLogs.Core || DebugLogs.Pot || DebugLogs.Botanist || DebugLogs.Chemist || DebugLogs.MixingStation)
				{
					MelonLogger.Msg("EntityConfigurationSelectedPatch: " + ((object)__instance).GetType()?.Name + " selected");
				}
				PotConfiguration val = (PotConfiguration)(object)((__instance is PotConfiguration) ? __instance : null);
				if (val != null && PotExtensions.SupplyRoute.TryGetValue(((BuildableItem)val.Pot).GUID, out var value))
				{
					if (value != null)
					{
						if (DebugLogs.All || DebugLogs.Core || DebugLogs.Pot || DebugLogs.Botanist)
						{
							MelonLogger.Msg("EntityConfigurationSelectedPatch: Enabling visuals for Pot SourceRoute");
						}
						value.SetVisualsActive(true);
					}
					else if (DebugLogs.All || DebugLogs.Core || DebugLogs.Botanist || DebugLogs.Pot)
					{
						MelonLogger.Warning("EntityConfigurationSelectedPatch: Pot SourceRoute is null");
					}
					return;
				}
				MixingStationConfiguration val2 = (MixingStationConfiguration)(object)((__instance is MixingStationConfiguration) ? __instance : null);
				if (val2 == null || !MixingStationExtensions.SupplyRoute.TryGetValue(((BuildableItem)val2.station).GUID, out var value2))
				{
					return;
				}
				if (value2 != null)
				{
					if (DebugLogs.All || DebugLogs.Core || DebugLogs.MixingStation || DebugLogs.Chemist)
					{
						MelonLogger.Msg("EntityConfigurationSelectedPatch: Enabling visuals for MixingStation SourceRoute");
					}
					value2.SetVisualsActive(true);
				}
				else if (DebugLogs.All || DebugLogs.Core || DebugLogs.Chemist || DebugLogs.MixingStation)
				{
					MelonLogger.Warning("EntityConfigurationSelectedPatch: MixingStation SourceRoute is null");
				}
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"EntityConfigurationSelectedPatch: Failed for {((object)__instance)?.GetType().Name}, error: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(EntityConfiguration), "Deselected")]
	public class EntityConfigurationDeselectedPatch
	{
		private static void Postfix(EntityConfiguration __instance)
		{
			try
			{
				if (DebugLogs.All || DebugLogs.Core)
				{
					MelonLogger.Msg("EntityConfigurationDeselectedPatch: " + ((object)__instance).GetType().Name + " deselected");
				}
				PotConfiguration val = (PotConfiguration)(object)((__instance is PotConfiguration) ? __instance : null);
				if (val != null && PotExtensions.SupplyRoute.TryGetValue(((BuildableItem)val.Pot).GUID, out var value))
				{
					if (value != null)
					{
						if (DebugLogs.All || DebugLogs.Core)
						{
							MelonLogger.Msg("EntityConfigurationDeselectedPatch: Disabling visuals for Pot SourceRoute");
						}
						value.SetVisualsActive(false);
					}
					else if (DebugLogs.All || DebugLogs.Core || DebugLogs.Chemist || DebugLogs.Botanist)
					{
						MelonLogger.Warning("EntityConfigurationDeselectedPatch: Pot SourceRoute is null");
					}
					return;
				}
				MixingStationConfiguration val2 = (MixingStationConfiguration)(object)((__instance is MixingStationConfiguration) ? __instance : null);
				if (val2 == null || !MixingStationExtensions.SupplyRoute.TryGetValue(((BuildableItem)val2.station).GUID, out var value2))
				{
					return;
				}
				if (value2 != null)
				{
					if (DebugLogs.All || DebugLogs.Core || DebugLogs.Chemist || DebugLogs.Botanist)
					{
						MelonLogger.Msg("EntityConfigurationDeselectedPatch: Disabling visuals for MixingStation SourceRoute");
					}
					value2.SetVisualsActive(false);
				}
				else if (DebugLogs.All || DebugLogs.Core || DebugLogs.Chemist || DebugLogs.Botanist)
				{
					MelonLogger.Warning("EntityConfigurationDeselectedPatch: MixingStation SourceRoute is null");
				}
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"EntityConfigurationDeselectedPatch: Failed for {((object)__instance)?.GetType().Name}, error: {arg}");
			}
		}
	}
	public static class UIExtensions
	{
		public static T GetField<T>(object obj, string fieldName) where T : Component
		{
			FieldInfo field = obj.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public);
			if (field == null)
			{
				Debug.LogError((object)("Field " + fieldName + " not found on " + obj.GetType().Name));
				return default(T);
			}
			object? value = field.GetValue(obj);
			return (T)((value is T) ? value : null);
		}

		public static void SetField(object obj, string fieldName, object value)
		{
			FieldInfo field = obj.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public);
			if (field == null)
			{
				Debug.LogError((object)("Field " + fieldName + " not found on " + obj.GetType().Name));
			}
			else
			{
				field.SetValue(obj, value);
			}
		}

		public static T CloneComponent<T>(T source, GameObject target) where T : Component
		{
			//IL_012c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0136: Expected O, but got Unknown
			if ((Object)(object)source == (Object)null || (Object)(object)target == (Object)null)
			{
				return default(T);
			}
			T val = target.AddComponent<T>();
			FieldInfo[] fields = typeof(T).GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				fieldInfo.SetValue(val, fieldInfo.GetValue(source));
			}
			PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (PropertyInfo propertyInfo in properties)
			{
				if (propertyInfo.CanRead && propertyInfo.CanWrite)
				{
					propertyInfo.SetValue(val, propertyInfo.GetValue(source));
				}
			}
			object obj = val;
			Button val2 = (Button)((obj is Button) ? obj : null);
			if (val2 != null)
			{
				Button sourceButton = default(Button);
				ref Button reference = ref sourceButton;
				object obj2 = source;
				reference = (Button)((obj2 is Button) ? obj2 : null);
				if (sourceButton != null)
				{
					((UnityEvent)val2.onClick).AddListener((UnityAction)delegate
					{
						((UnityEvent)sourceButton.onClick).Invoke();
					});
				}
			}
			return val;
		}
	}
	[HarmonyPatch(typeof(LoadManager))]
	public class LoadManagerPatch
	{
		[Serializable]
		[CompilerGenerated]
		private sealed class <>c
		{
			public static readonly <>c <>9 = new <>c();

			public static UnityAction <>9__0_0;

			internal void <Postfix>b__0_0()
			{
				if (DebugLogs.All || DebugLogs.Core)
				{
					MelonLogger.Msg("onLoadComplete fired, restoring configurations");
				}
				PotExtensions.RestoreConfigurations();
				MixingStationExtensions.RestoreConfigurations();
			}
		}

		[HarmonyPostfix]
		[HarmonyPatch("Awake")]
		private static void Postfix(LoadManager __instance)
		{
			//IL_001c: Unknown result type (might be due to invalid IL or missing references)
			//IL_0021: Unknown result type (might be due to invalid IL or missing references)
			//IL_0027: Expected O, but got Unknown
			try
			{
				UnityEvent onLoadComplete = __instance.onLoadComplete;
				object obj = <>c.<>9__0_0;
				if (obj == null)
				{
					UnityAction val = delegate
					{
						if (DebugLogs.All || DebugLogs.Core)
						{
							MelonLogger.Msg("onLoadComplete fired, restoring configurations");
						}
						PotExtensions.RestoreConfigurations();
						MixingStationExtensions.RestoreConfigurations();
					};
					<>c.<>9__0_0 = val;
					obj = (object)val;
				}
				onLoadComplete.AddListener((UnityAction)obj);
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"LoadManagerPatch.Awake failed: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(GridItemLoader), "LoadAndCreate")]
	public class GridItemLoaderPatch
	{
		public static Dictionary<string, GridItem> LoadedGridItems = new Dictionary<string, GridItem>();

		private static void Postfix(string mainPath, GridItem __result)
		{
			try
			{
				if (DebugLogs.All || DebugLogs.Core)
				{
					MelonLogger.Msg("GridItemLoaderPatch: Processing LoadAndCreate for mainPath: " + mainPath);
				}
				if ((Object)(object)__result != (Object)null)
				{
					LoadedGridItems[mainPath] = __result;
					if (DebugLogs.All || DebugLogs.Core)
					{
						MelonLogger.Msg("GridItemLoaderPatch: Captured GridItem (type: " + ((object)__result).GetType().Name + ") for mainPath: " + mainPath);
					}
				}
				else if (DebugLogs.All || DebugLogs.Core)
				{
					MelonLogger.Warning("GridItemLoaderPatch: No GridItem returned for mainPath: " + mainPath);
				}
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"GridItemLoaderPatch: Postfix failed for mainPath: {mainPath}, error: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(ConfigurationReplicator), "RpcLogic___ReceiveItemField_2801973956")]
	public class ConfigurationReplicatorReceiveItemFieldPatch
	{
		private static bool Prefix(ConfigurationReplicator __instance, int fieldIndex, string value)
		{
			if (DebugLogs.All || DebugLogs.Core)
			{
				MelonLogger.Msg(string.Format("ConfigurationReplicatorReceiveItemFieldPatch: Received update for fieldIndex={0}, value={1}", fieldIndex, value ?? "null"));
				MelonLogger.Msg($"ConfigurationReplicatorReceiveItemFieldPatch: Fields count={__instance.Configuration.Fields.Count}");
				for (int i = 0; i < __instance.Configuration.Fields.Count; i++)
				{
					MelonLogger.Msg(string.Format("ConfigurationReplicatorReceiveItemFieldPatch: Fields[{0}]={1}", i, ((object)__instance.Configuration.Fields[i])?.GetType().Name ?? "null"));
				}
			}
			if (fieldIndex < 0 || fieldIndex >= __instance.Configuration.Fields.Count)
			{
				if (DebugLogs.All || DebugLogs.Core)
				{
					MelonLogger.Msg($"ConfigurationReplicatorReceiveItemFieldPatch: Invalid fieldIndex={fieldIndex}, Configuration.Fields.Count={__instance.Configuration.Fields.Count}, skipping");
				}
				return false;
			}
			ConfigField obj = __instance.Configuration.Fields[fieldIndex];
			ItemField val = (ItemField)(object)((obj is ItemField) ? obj : null);
			if (val == null)
			{
				if (DebugLogs.All || DebugLogs.Core)
				{
					MelonLogger.Msg(string.Format("ConfigurationReplicatorReceiveItemFieldPatch: No ItemField at fieldIndex={0}, Fields[{1}]={2}, skipping", fieldIndex, fieldIndex, ((object)__instance.Configuration.Fields[fieldIndex])?.GetType().Name ?? "null"));
				}
				return false;
			}
			if (string.IsNullOrEmpty(value) && !val.CanSelectNone)
			{
				if (DebugLogs.All || DebugLogs.Core)
				{
					MelonLogger.Msg(string.Format("ConfigurationReplicatorReceiveItemFieldPatch: Blocked null update for ItemField with CanSelectNone={0}, CurrentItem={1}", val.CanSelectNone, val.SelectedItem?.Name ?? "null"));
				}
				return false;
			}
			if (DebugLogs.All || DebugLogs.Core)
			{
				MelonLogger.Msg($"ConfigurationReplicatorReceiveItemFieldPatch: Allowing update for ItemField, CanSelectNone={val.CanSelectNone}, value={value}");
			}
			return true;
		}

		private static void Postfix(ConfigurationReplicator __instance, int fieldIndex, string value)
		{
			try
			{
				if (DebugLogs.All || DebugLogs.Core || DebugLogs.Chemist || DebugLogs.Botanist)
				{
					MelonLogger.Msg($"ConfigurationReplicatorReceiveObjectFieldPatch: Received update for fieldIndex={fieldIndex}, value={value}");
				}
				EntityConfiguration configuration = __instance.Configuration;
				PotConfiguration val = (PotConfiguration)(object)((configuration is PotConfiguration) ? configuration : null);
				if (val == null || fieldIndex != 6)
				{
					return;
				}
				if (PotExtensions.Supply.TryGetValue(((BuildableItem)val.Pot).GUID, out var _))
				{
					if (DebugLogs.All || DebugLogs.Core || DebugLogs.Chemist || DebugLogs.Botanist)
					{
						MelonLogger.Msg($"ConfigurationReplicatorReceiveObjectFieldPatch: Updated supply for pot: {((BuildableItem)val.Pot).GUID}, SelectedObject: unknown because value is a string");
					}
				}
				else if (DebugLogs.All || DebugLogs.Core || DebugLogs.Chemist || DebugLogs.Botanist)
				{
					MelonLogger.Warning($"ConfigurationReplicatorReceiveObjectFieldPatch: No supply found for pot: {((BuildableItem)val.Pot).GUID}");
				}
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"ConfigurationReplicatorReceiveObjectFieldPatch: Failed for fieldIndex={fieldIndex}, error: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(ItemField), "SetItem", new Type[]
	{
		typeof(ItemDefinition),
		typeof(bool)
	})]
	public class ItemFieldSetItemPatch
	{
		private static bool Prefix(ItemField __instance, ItemDefinition item, bool network)
		{
			if (DebugLogs.Stacktrace)
			{
				MelonLogger.Msg(string.Format("ItemFieldSetItemPatch: Called for ItemField, network={0}, CanSelectNone={1}, Item={2}, CurrentItem={3}, StackTrace: {4}", network, __instance.CanSelectNone, item?.Name ?? "null", __instance.SelectedItem?.Name ?? "null", new StackTrace().ToString()));
			}
			bool flag = __instance.Options != null && __instance.Options.Any((ItemDefinition o) => ((IEnumerable<ItemDefinition>)ProductManager.FavouritedProducts).Contains(o));
			if ((((Object)(object)item == (Object)null && __instance.CanSelectNone) || flag) && DebugLogs.Stacktrace)
			{
				MelonLogger.Msg(string.Format("ItemFieldSetItemPatch: Blocked null update for Product field, CanSelectNone={0}, CurrentItem={1}, StackTrace: {2}", __instance.CanSelectNone, __instance.SelectedItem?.Name ?? "null", new StackTrace().ToString()));
			}
			return true;
		}
	}
}
namespace NoLazyWorkers.Settings
{
	public class SettingsExtensions
	{
		public static readonly List<Guid> Configured = new List<Guid>();
	}
	[Serializable]
	public class BaseEmployee
	{
		public string SigningFee { get; set; }

		public string DailyWage { get; set; }

		public string WalkSpeed { get; set; }

		public string MaxHealth { get; set; }
	}
	[Serializable]
	public class BotanistSettings : BaseEmployee
	{
		public string SoilPourTime { get; set; }

		public string SeedSowTime { get; set; }

		public string AdditivePourTime { get; set; }

		public string WaterPourTime { get; set; }

		public string WateringCriticalThreshold { get; set; }

		public string WateringThreshold { get; set; }

		public string WateringTargetMin { get; set; }

		public string WateringTargetMax { get; set; }

		public string HarvestTime { get; set; }
	}
	[Serializable]
	public class ChemistSettings : BaseEmployee
	{
		public string MixingPerIngredientTime { get; set; }

		public string PlaceIngredientsTime { get; set; }

		public string StirTime { get; set; }

		public string BurnerTime { get; set; }
	}
	[Serializable]
	public class CleanerSettings : BaseEmployee
	{
	}
	[Serializable]
	public class PackagerSettings : BaseEmployee
	{
		public string PackagingSpeedMultiplier { get; set; }
	}
	[Serializable]
	public class FixerSettings
	{
		public string AdditionalSigningFee1 { get; set; }

		public string AdditionalSigningFee2 { get; set; }

		public string MaxAdditionalFee { get; set; }

		public string AdditionalFeeThreshold { get; set; }
	}
	[Serializable]
	public class MiscSettings
	{
		public string StoreDeliveryFee { get; set; }
	}
	[Serializable]
	public class Default
	{
		public BotanistSettings Botanist { get; set; } = new BotanistSettings();


		public ChemistSettings Chemist { get; set; } = new ChemistSettings();


		public CleanerSettings Cleaner { get; set; } = new CleanerSettings();


		public PackagerSettings Packager { get; set; } = new PackagerSettings();


		public FixerSettings Fixer { get; set; } = new FixerSettings();


		public MiscSettings Misc { get; set; } = new MiscSettings();


		public static Default LoadFromFile(string filePath)
		{
			if (DebugLogs.All || DebugLogs.Settings)
			{
				MelonLogger.Msg("Settings: LoadFromFile");
			}
			Default @default = new Default();
			string text = "";
			string[] array = File.ReadAllLines(filePath);
			foreach (string text2 in array)
			{
				string text3 = text2.Trim();
				if (string.IsNullOrEmpty(text3) || text3.StartsWith("//"))
				{
					continue;
				}
				if (text3.StartsWith("#"))
				{
					text = text3.Substring(1).ToLower();
					continue;
				}
				string[] array2 = (from p in text3.Split('=')
					select p.Trim()).ToArray();
				if (array2.Length == 2)
				{
					string key = array2[0];
					string value = array2[1];
					switch (text)
					{
					case "botanist":
						SetProperty(@default.Botanist, key, value);
						break;
					case "chemist":
						SetProperty(@default.Chemist, key, value);
						break;
					case "cleaner":
						SetProperty(@default.Cleaner, key, value);
						break;
					case "packager":
						SetProperty(@default.Packager, key, value);
						break;
					case "fixer":
						SetProperty(@default.Fixer, key, value);
						break;
					case "misc":
						SetProperty(@default.Misc, key, value);
						break;
					}
				}
			}
			return @default;
		}

		private static void SetProperty(object target, string key, string value)
		{
			if (DebugLogs.All || DebugLogs.Settings)
			{
				MelonLogger.Msg("Settings: SetProperty");
			}
			PropertyInfo property = target.GetType().GetProperty(key, BindingFlags.IgnoreCase | BindingFlags.Instance | BindingFlags.Public);
			if (!(property == null) && !(property.PropertyType != typeof(string)))
			{
				if (DebugLogs.All || DebugLogs.Settings)
				{
					MelonLogger.Msg($"Settings: SetProperty {property} | {target}");
				}
				property.SetValue(target, value);
			}
		}

		public void SaveToFile(string filePath)
		{
			if (DebugLogs.All || DebugLogs.Settings)
			{
				MelonLogger.Msg("Settings: SaveToFile");
			}
			List<string> contents = new List<string>
			{
				"#botanist",
				"SigningFee = " + Botanist.SigningFee,
				"DailyWage = " + Botanist.DailyWage,
				"WalkSpeed = " + Botanist.WalkSpeed,
				"MaxHealth = " + Botanist.MaxHealth,
				"SoilPourTime = " + Botanist.SoilPourTime,
				"SeedSowTime = " + Botanist.SeedSowTime,
				"AdditivePourTime = " + Botanist.AdditivePourTime,
				"WaterPourTime = " + Botanist.WaterPourTime,
				"WateringCriticalThreshold = " + Botanist.WateringCriticalThreshold,
				"WateringThreshold = " + Botanist.WateringThreshold,
				"WateringTargetMin = " + Botanist.WateringTargetMin,
				"WateringTargetMax = " + Botanist.WateringTargetMax,
				"HarvestTime = " + Botanist.HarvestTime,
				"",
				"#chemist",
				"SigningFee = " + Chemist.SigningFee,
				"DailyWage = " + Chemist.DailyWage,
				"WalkSpeed = " + Chemist.WalkSpeed,
				"MaxHealth = " + Chemist.MaxHealth,
				"#MixingPerIngredientTime = " + Chemist.MixingPerIngredientTime + " #not implemented yet",
				"#PlaceIngredientsTime = " + Chemist.PlaceIngredientsTime + " #not implemented yet",
				"#StirTime = " + Chemist.StirTime + " #not implemented yet",
				"#BurnerTime = " + Chemist.BurnerTime + " #not implemented yet",
				"",
				"#cleaner",
				"SigningFee = " + Cleaner.SigningFee,
				"DailyWage = " + Cleaner.DailyWage,
				"WalkSpeed = " + Cleaner.WalkSpeed,
				"MaxHealth = " + Cleaner.MaxHealth,
				"",
				"#packager",
				"SigningFee = " + Packager.SigningFee,
				"DailyWage = " + Packager.DailyWage,
				"WalkSpeed = " + Packager.WalkSpeed,
				"MaxHealth = " + Packager.MaxHealth,
				"PackagingSpeedMultiplier = " + Packager.PackagingSpeedMultiplier,
				"",
				"#fixer",
				"#AdditionalSigningFee1 = " + Fixer.AdditionalSigningFee1 + " #not implemented yet",
				"#AdditionalSigningFee2 = " + Fixer.AdditionalSigningFee2 + " #not implemented yet",
				"#MaxAdditionalFee = " + Fixer.MaxAdditionalFee + " #not implemented yet",
				"#AdditionalFeeThreshold = " + Fixer.AdditionalFeeThreshold + " #not implemented yet",
				"",
				"#misc",
				"#StoreDeliveryFee = " + Misc.StoreDeliveryFee + " #not implemented yet"
			};
			File.WriteAllLines(filePath, contents);
		}

		public Default()
		{
			if (DebugLogs.All || DebugLogs.Settings)
			{
				MelonLogger.Msg("Settings: Default");
			}
			Botanist = new BotanistSettings
			{
				SigningFee = "1000",
				DailyWage = "200",
				WalkSpeed = "1.2",
				MaxHealth = "100",
				SoilPourTime = "10",
				SeedSowTime = "15",
				AdditivePourTime = "10",
				WaterPourTime = "10",
				WateringCriticalThreshold = "0.2",
				WateringThreshold = "0.3",
				WateringTargetMin = "0.75",
				WateringTargetMax = "1",
				HarvestTime = "15"
			};
			Chemist = new ChemistSettings
			{
				SigningFee = "1500",
				DailyWage = "300",
				WalkSpeed = "1.2",
				MaxHealth = "100",
				MixingPerIngredientTime = "1",
				PlaceIngredientsTime = "8",
				StirTime = "6",
				BurnerTime = "6"
			};
			Cleaner = new CleanerSettings
			{
				SigningFee = "500",
				DailyWage = "100",
				WalkSpeed = "1.2",
				MaxHealth = "100"
			};
			Packager = new PackagerSettings
			{
				SigningFee = "1000",
				DailyWage = "200",
				WalkSpeed = "1.2",
				MaxHealth = "100",
				PackagingSpeedMultiplier = "2"
			};
			Fixer = new FixerSettings
			{
				AdditionalSigningFee1 = "100",
				AdditionalSigningFee2 = "250",
				MaxAdditionalFee = "500",
				AdditionalFeeThreshold = "5"
			};
			Misc = new MiscSettings
			{
				StoreDeliveryFee = "200"
			};
		}
	}
	public class Configure
	{
		[CompilerGenerated]
		private sealed class <ApplyOneShotSettingsRoutine>d__10 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public Configure <>4__this;

			private bool <settingsApplied>5__1;

			private float <elapsedTime>5__2;

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

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

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

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

			private bool MoveNext()
			{
				//IL_00af: Unknown result type (might be due to invalid IL or missing references)
				//IL_00b9: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					if (DebugLogs.All || DebugLogs.Settings)
					{
						MelonLogger.Msg("Settings: ApplyOneShotSettingsRoutine started");
					}
					<settingsApplied>5__1 = false;
					<elapsedTime>5__2 = 0f;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (<elapsedTime>5__2 < 30f && !<settingsApplied>5__1)
				{
					if (DebugLogs.All || DebugLogs.Settings)
					{
						MelonLogger.Msg($"Settings: ApplyOneShotSettingsRoutine attempt at {<elapsedTime>5__2} seconds");
					}
					<>4__this.ApplyMiscSettings();
					<settingsApplied>5__1 = true;
					<elapsedTime>5__2 += 1f;
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 1;
					return true;
				}
				if (<settingsApplied>5__1)
				{
					if (DebugLogs.All || DebugLogs.Settings)
					{
						MelonLogger.Msg("Settings: ApplyOneShotSettingsRoutine completed successfully");
					}
				}
				else
				{
					MelonLogger.Error("Settings: ApplyOneShotSettingsRoutine failed to apply settings after 30 seconds");
				}
				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 <ConfigureRoutine>d__3 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public Employee employee;

			public Configure <>4__this;

			private int <attempts>5__1;

			private int <objectId>5__2;

			private bool <isObjectIdValid>5__3;

			private string <guid>5__4;

			private bool <isGuidValid>5__5;

			private Exception <ex>5__6;

			private EEmployeeType <>s__7;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<guid>5__4 = null;
				<ex>5__6 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_025b: Unknown result type (might be due to invalid IL or missing references)
				//IL_0260: Unknown result type (might be due to invalid IL or missing references)
				//IL_0262: Unknown result type (might be due to invalid IL or missing references)
				//IL_0264: Unknown result type (might be due to invalid IL or missing references)
				//IL_026a: Unknown result type (might be due to invalid IL or missing references)
				//IL_026f: Unknown result type (might be due to invalid IL or missing references)
				//IL_0271: Unknown result type (might be due to invalid IL or missing references)
				//IL_0288: Expected I4, but got Unknown
				//IL_02f9: 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)(object)employee == (Object)null)
					{
						MelonLogger.Error("Settings: ConfigureRoutine: Employee is null");
						return false;
					}
					<attempts>5__1 = 0;
					break;
				case 1:
					<>1__state = -1;
					<guid>5__4 = null;
					break;
				}
				if (<attempts>5__1 < 50)
				{
					<objectId>5__2 = 0;
					<isObjectIdValid>5__3 = false;
					try
					{
						<objectId>5__2 = ((NetworkBehaviour)employee).ObjectId;
						<isObjectIdValid>5__3 = <objectId>5__2 != 0;
					}
					catch (Exception ex)
					{
						<ex>5__6 = ex;
						if (DebugLogs.All || DebugLogs.Settings)
						{
							MelonLogger.Msg($"Settings: ConfigureRoutine: Error accessing ObjectId for {((NPC)employee).fullName} on attempt {<attempts>5__1 + 1}: {<ex>5__6.Message}");
						}
					}
					<guid>5__4 = ((NPC)employee).GUID.ToString();
					<isGuidValid>5__5 = !string.IsNullOrEmpty(<guid>5__4) && <guid>5__4 != "00000000-0000-0000-0000-000000000000";
					if (DebugLogs.All || DebugLogs.Settings)
					{
						MelonLogger.Msg(string.Format("Settings: ConfigureRoutine: Waiting for valid ObjectId and GUID for {0} | Attempt {1} | ObjectId: {2} | GUID: {3}", ((NPC)employee).fullName, <attempts>5__1 + 1, <isObjectIdValid>5__3 ? <objectId>5__2.ToString() : "Invalid", <guid>5__4));
					}
					if (<isObjectIdValid>5__3 & <isGuidValid>5__5)
					{
						if (SettingsExtensions.Configured.Contains(((NPC)employee).GUID))
						{
							if (DebugLogs.All || DebugLogs.Settings)
							{
								MelonLogger.Msg($"Settings: ConfigureRoutine: Skipping already configured employee {((NPC)employee).fullName} | ObjectId: {<objectId>5__2} | GUID: {<guid>5__4}");
							}
							return false;
						}
						SettingsExtensions.Configured.Add(((NPC)employee).GUID);
						if (DebugLogs.All || DebugLogs.Settings)
						{
							MelonLogger.Msg($"Settings: ConfigureRoutine: Added ObjectId {<objectId>5__2} for {((NPC)employee).fullName} | GUID: {<guid>5__4}");
						}
						EEmployeeType type = employee.Type;
						<>s__7 = type;
						EEmployeeType val = <>s__7;
						switch ((int)val)
						{
						case 0:
						{
							Configure configure4 = <>4__this;
							Employee obj4 = employee;
							configure4.ApplyBotanistSettings((Botanist)(object)((obj4 is Botanist) ? obj4 : null));
							break;
						}
						case 2:
						{
							Configure configure3 = <>4__this;
							Employee obj3 = employee;
							configure3.ApplyChemistSettings((Chemist)(object)((obj3 is Chemist) ? obj3 : null));
							break;
						}
						case 3:
						{
							Configure configure2 = <>4__this;
							Employee obj2 = employee;
							configure2.ApplyCleanerSettings((Cleaner)(object)((obj2 is Cleaner) ? obj2 : null));
							break;
						}
						case 1:
						{
							Configure configure = <>4__this;
							Employee obj = employee;
							configure.ApplyPackagerSettings((Packager)(object)((obj is Packager) ? obj : null));
							break;
						}
						default:
							MelonLogger.Warning($"Settings: ConfigureRoutine: Unknown employee type {employee.Type} for {((NPC)employee).fullName}");
							break;
						}
						return false;
					}
					<attempts>5__1++;
					<>2__current = null;
					<>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();
			}
		}

		private readonly Default config;

		public Configure()
		{
			if (DebugLogs.All || DebugLogs.Settings)
			{
				MelonLogger.Msg("Settings: Configure");
			}
			config = NoLazyWorkersMod.Instance.Config;
		}

		public void StartCoroutine(Employee employee)
		{
			if ((Object)(object)employee == (Object)null)
			{
				MelonLogger.Error("Settings: StartCoroutine: Employee is null");
			}
			else
			{
				MelonCoroutines.Start(ConfigureRoutine(employee));
			}
		}

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

		public void ApplyBotanistSettings(Botanist botanist)
		{
			if ((Object)(object)botanist == (Object)null)
			{
				MelonLogger.Error("Settings: ApplyBotanistSettings: Botanist is null");
				return;
			}
			if (DebugLogs.All || DebugLogs.Settings)
			{
				MelonLogger.Msg($"Settings: ApplyBotanistSettings {((NPC)botanist).fullName} | {((NetworkBehaviour)botanist).ObjectId} | {((NPC)botanist).GUID}");
			}
			if (int.TryParse(config.Botanist.SigningFee, out var result))
			{
				((Employee)botanist).SigningFee = result;
			}
			else
			{
				MelonLogger.Error("Invalid SigningFee for Botanist: " + config.Botanist.SigningFee);
			}
			if (int.TryParse(config.Botanist.DailyWage, out var result2))
			{
				((Employee)botanist).DailyWage = result2;
			}
			else
			{
				MelonLogger.Error("Invalid DailyWage for Botanist: " + config.Botanist.DailyWage);
			}
			if (float.TryParse(config.Botanist.WalkSpeed, out var result3))
			{
				((NPC)botanist).movement.WalkSpeed = result3;
			}
			else
			{
				MelonLogger.Error("Invalid WalkSpeed for Botanist: " + config.Botanist.WalkSpeed);
			}
			if (float.TryParse(config.Botanist.MaxHealth, out var result4))
			{
				((NPC)botanist).Health.MaxHealth = result4;
			}
			else
			{
				MelonLogger.Error("Invalid MaxHealth for Botanist: " + config.Botanist.MaxHealth);
			}
			if (float.TryParse(config.Botanist.SoilPourTime, out var result5))
			{
				botanist.SOIL_POUR_TIME = result5;
			}
			else
			{
				MelonLogger.Error("Invalid SoilPourTime for Botanist: " + config.Botanist.SoilPourTime);
			}
			if (float.TryParse(config.Botanist.SeedSowTime, out var result6))
			{
				botanist.SEED_SOW_TIME = result6;
			}
			else
			{
				MelonLogger.Error("Invalid SeedSowTime for Botanist: " + config.Botanist.SeedSowTime);
			}
			if (float.TryParse(config.Botanist.AdditivePourTime, out var result7))
			{
				botanist.ADDITIVE_POUR_TIME = result7;
			}
			else
			{
				MelonLogger.Error("Invalid AdditivePourTime for Botanist: " + config.Botanist.AdditivePourTime);
			}
			if (float.TryParse(config.Botanist.WateringCriticalThreshold, out var result8))
			{
				botanist.CRITICAL_WATERING_THRESHOLD = result8;
			}
			else
			{
				MelonLogger.Error("Invalid WateringCriticalThreshold for Botanist: " + config.Botanist.WateringCriticalThreshold);
			}
			if (float.TryParse(config.Botanist.WateringThreshold, out var result9))
			{
				botanist.WATERING_THRESHOLD = result9;
			}
			else
			{
				MelonLogger.Error("Invalid WateringThreshold for Botanist: " + config.Botanist.WateringThreshold);
			}
			if (float.TryParse(config.Botanist.WateringTargetMin, out var result10))
			{
				botanist.TARGET_WATER_LEVEL_MIN = result10;
			}
			else
			{
				MelonLogger.Error("Invalid WateringTargetMin for Botanist: " + config.Botanist.WateringTargetMin);
			}
			if (float.TryParse(config.Botanist.WateringTargetMax, out var result11))
			{
				botanist.TARGET_WATER_LEVEL_MAX = result11;
			}
			else
			{
				MelonLogger.Error("Invalid WateringTargetMax for Botanist: " + config.Botanist.WateringTargetMax);
			}
			if (float.TryParse(config.Botanist.WaterPourTime, out var result12))
			{
				botanist.WATER_POUR_TIME = result12;
			}
			else
			{
				MelonLogger.Error("Invalid WaterPourTime for Botanist: " + config.Botanist.WaterPourTime);
			}
			if (float.TryParse(config.Botanist.HarvestTime, out var result13))
			{
				botanist.HARVEST_TIME = result13;
			}
			else
			{
				MelonLogger.Error("Invalid HarvestTime for Botanist: " + config.Botanist.HarvestTime);
			}
		}

		public void ApplyChemistSettings(Chemist chemist)
		{
			if ((Object)(object)chemist == (Object)null)
			{
				MelonLogger.Error("Settings: ApplyChemistSettings: Chemist is null");
				return;
			}
			if (DebugLogs.All || DebugLogs.Settings)
			{
				MelonLogger.Msg($"Settings: ApplyChemistSettings {((NPC)chemist).fullName} | {((NetworkBehaviour)chemist).ObjectId} | {((NPC)chemist).GUID}");
			}
			if (int.TryParse(config.Chemist.SigningFee, out var result))
			{
				((Employee)chemist).SigningFee = result;
			}
			else
			{
				MelonLogger.Error("Invalid SigningFee for Chemist: " + config.Chemist.SigningFee);
			}
			if (int.TryParse(config.Chemist.DailyWage, out var result2))
			{
				((Employee)chemist).DailyWage = result2;
			}
			else
			{
				MelonLogger.Error("Invalid DailyWage for Chemist: " + config.Chemist.DailyWage);
			}
			if (float.TryParse(config.Chemist.WalkSpeed, out var result3))
			{
				((NPC)chemist).movement.WalkSpeed = result3;
			}
			else
			{
				MelonLogger.Error("Invalid WalkSpeed for Chemist: " + config.Chemist.WalkSpeed);
			}
			if (float.TryParse(config.Chemist.MaxHealth, out var result4))
			{
				((NPC)chemist).Health.MaxHealth = result4;
			}
			else
			{
				MelonLogger.Error("Invalid MaxHealth for Chemist: " + config.Chemist.MaxHealth);
			}
		}

		public void ApplyCleanerSettings(Cleaner cleaner)
		{
			if ((Object)(object)cleaner == (Object)null)
			{
				MelonLogger.Error("Settings: ApplyCleanerSettings: Cleaner is null");
				return;
			}
			if (DebugLogs.All || DebugLogs.Settings)
			{
				MelonLogger.Msg($"Settings: ApplyCleanerSettings {((NPC)cleaner).fullName} | {((NetworkBehaviour)cleaner).ObjectId} | {((NPC)cleaner).GUID}");
			}
			if (int.TryParse(config.Cleaner.SigningFee, out var result))
			{
				((Employee)cleaner).SigningFee = result;
			}
			else
			{
				MelonLogger.Error("Invalid SigningFee for Cleaner: " + config.Cleaner.SigningFee);
			}
			if (int.TryParse(config.Cleaner.DailyWage, out var result2))
			{
				((Employee)cleaner).DailyWage = result2;
			}
			else
			{
				MelonLogger.Error("Invalid DailyWage for Cleaner: " + config.Cleaner.DailyWage);
			}
			if (float.TryParse(config.Cleaner.WalkSpeed, out var result3))
			{
				((NPC)cleaner).movement.WalkSpeed = result3;
			}
			else
			{
				MelonLogger.Error("Invalid WalkSpeed for Cleaner: " + config.Cleaner.WalkSpeed);
			}
			if (float.TryParse(config.Cleaner.MaxHealth, out var result4))
			{
				((NPC)cleaner).Health.MaxHealth = result4;
			}
			else
			{
				MelonLogger.Error("Invalid MaxHealth for Cleaner: " + config.Cleaner.MaxHealth);
			}
		}

		public void ApplyPackagerSettings(Packager packager)
		{
			if ((Object)(object)packager == (Object)null)
			{
				MelonLogger.Error("Settings: ApplyPackagerSettings: Packager is null");
				return;
			}
			if (DebugLogs.All || DebugLogs.Settings)
			{
				MelonLogger.Msg($"Settings: ApplyPackagerSettings {((NPC)packager).fullName} | {((NetworkBehaviour)packager).ObjectId} | {((NPC)packager).GUID}");
			}
			if (int.TryParse(config.Packager.SigningFee, out var result))
			{
				((Employee)packager).SigningFee = result;
			}
			else
			{
				MelonLogger.Error("Invalid SigningFee for Packager: " + config.Packager.SigningFee);
			}
			if (int.TryParse(config.Packager.DailyWage, out var result2))
			{
				((Employee)packager).DailyWage = result2;
			}
			else
			{
				MelonLogger.Error("Invalid DailyWage for Packager: " + config.Packager.DailyWage);
			}
			if ((Object)(object)((NPC)packager).movement != (Object)null && float.TryParse(config.Packager.WalkSpeed, out var result3))
			{
				((NPC)packager).movement.WalkSpeed = result3;
			}
			else
			{
				MelonLogger.Error("Invalid WalkSpeed for Packager: " + config.Packager.WalkSpeed + " or movement is null");
			}
			if ((Object)(object)((NPC)packager).Health != (Object)null && float.TryParse(config.Packager.MaxHealth, out var result4))
			{
				((NPC)packager).Health.MaxHealth = result4;
			}
			else
			{
				MelonLogger.Error("Invalid MaxHealth for Packager: " + config.Packager.MaxHealth + " or Health is null");
			}
			if (float.TryParse(config.Packager.PackagingSpeedMultiplier, out var result5))
			{
				packager.PackagingSpeedMultiplier = result5;
			}
			else
			{
				MelonLogger.Error("Invalid PackagingSpeedMultiplier for Packager: " + config.Packager.PackagingSpeedMultiplier);
			}
		}

		public void ApplyFixerSettings()
		{
		}

		public void ApplyMiscSettings()
		{
			if (DebugLogs.All || DebugLogs.Settings)
			{
				MelonLogger.Msg("Settings: ApplyMiscSettings");
			}
			if (!float.TryParse(config.Misc.StoreDeliveryFee, out var _))
			{
				MelonLogger.Error("Invalid StoreDeliveryFee: " + config.Misc.StoreDeliveryFee);
			}
		}

		[IteratorStateMachine(typeof(<ApplyOneShotSettingsRoutine>d__10))]
		public IEnumerator ApplyOneShotSettingsRoutine()
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <ApplyOneShotSettingsRoutine>d__10(0)
			{
				<>4__this = this
			};
		}
	}
	[HarmonyPatch]
	public static class EmployeePatches
	{
		[HarmonyPostfix]
		[HarmonyPatch(typeof(Chemist), "NetworkInitialize___Early")]
		public static void ChemistNetworkInitializePostfix(Chemist __instance)
		{
			if (DebugLogs.All || DebugLogs.Settings)
			{
				MelonLogger.Msg("Settings: ChemistNetworkInitializePostfix");
			}
			ConfigureEmployee((Employee)(object)__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Packager), "NetworkInitialize___Early")]
		public static void PackagerNetworkInitializePostfix(Packager __instance)
		{
			if (DebugLogs.All || DebugLogs.Settings)
			{
				MelonLogger.Msg("Settings: PackagerNetworkInitializePostfix");
			}
			ConfigureEmployee((Employee)(object)__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Botanist), "NetworkInitialize___Early")]
		public static void BotanistNetworkInitializePostfix(Botanist __instance)
		{
			if (DebugLogs.All || DebugLogs.Settings)
			{
				MelonLogger.Msg("Settings: BotanistNetworkInitializePostfix");
			}
			ConfigureEmployee((Employee)(object)__instance);
		}

		[HarmonyPostfix]
		[HarmonyPatch(typeof(Cleaner), "NetworkInitialize___Early")]
		public static void CleanerNetworkInitializePostfix(Cleaner __instance)
		{
			if (DebugLogs.All || DebugLogs.Settings)
			{
				MelonLogger.Msg("Settings: CleanerNetworkInitializePostfix");
			}
			ConfigureEmployee((Employee)(object)__instance);
		}

		private static void ConfigureEmployee(Employee employee)
		{
			if ((Object)(object)employee == (Object)null)
			{
				MelonLogger.Error("Settings: ConfigureEmployee: Employee is null");
			}
			else if (SettingsExtensions.Configured.Contains(((NPC)employee).GUID))
			{
				if (DebugLogs.All || DebugLogs.Settings)
				{
					MelonLogger.Msg($"Settings: ConfigureEmployee: Skipping already configured employee {((NPC)employee).fullName} | ObjectId: {((NetworkBehaviour)employee).ObjectId} | GUID: {((NPC)employee).GUID}");
				}
			}
			else
			{
				new Configure().StartCoroutine(employee);
			}
		}
	}
}
namespace NoLazyWorkers.Handlers
{
	public static class PackagerExtensions
	{
	}
	[HarmonyPatch(typeof(AdvancedTransitRoute))]
	public class AdvancedTransitRoutePatch
	{
		[HarmonyPatch("GetItemReadyToMove")]
		[HarmonyPrefix]
		private static bool GetItemReadyToMovePrefix(AdvancedTransitRoute __instance, ref ItemInstance __result)
		{
			ITransitEntity destination = ((TransitRoute)__instance).Destination;
			MixingStation val = (MixingStation)(object)((destination is MixingStation) ? destination : null);
			if (val == null)
			{
				return true;
			}
			if (((IUsable)val).IsInUse || val.CurrentMixOperation != null || val.OutputSlot.Quantity > 0)
			{
				if (DebugLogs.All || DebugLogs.Packager)
				{
					MelonLogger.Msg($"Handlers: GetItemReadyToMovePrefix: Skipping {((BuildableItem)val).GUID} - Station in use, in operation, or output slot not empty (IsInUse={((IUsable)val).IsInUse}, CurrentMixOperation={val.CurrentMixOperation != null}, OutputQuantity={val.OutputSlot.Quantity})");
				}
				__result = null;
				return false;
			}
			if (DebugLogs.All || DebugLogs.Packager)
			{
				MelonLogger.Msg("Handlers: GetItemReadyToMovePrefix: resume");
			}
			return true;
		}
	}
	public static class StorageExtensions
	{
		public const int StorageEnum = 345543;

		public static StorageConfigPanel ConfigPanelTemplate;

		public static Dictionary<Guid, StorageConfiguration> StorageConfig = new Dictionary<Guid, StorageConfiguration>();

		public static void InitializeStaticStorageConfigPanelTemplate()
		{
			GetStorageConfigPanelTemplate();
		}

		public static StorageConfigPanel GetStorageConfigPanelTemplate()
		{
			try
			{
				if ((Object)(object)ConfigPanelTemplate != (Object)null)
				{
					return ConfigPanelTemplate;
				}
				Transform transformTemplateFromConfigPanel = NoLazyUtilities.GetTransformTemplateFromConfigPanel((EConfigurableType)0, "");
				GameObject val = Object.Instantiate<GameObject>(((Component)transformTemplateFromConfigPanel).gameObject);
				((Object)val).name = "StorageConfigPanel";
				val.AddComponent<CanvasRenderer>();
				PotConfigPanel component = val.GetComponent<PotConfigPanel>();
				if ((Object)(object)component == (Object)null)
				{
					return null;
				}
				Object.Destroy((Object)(object)component);
				StorageConfigPanel storageConfigPanel = val.AddComponent<StorageConfigPanel>();
				if ((Object)(object)storageConfigPanel == (Object)null)
				{
					MelonLogger.Error("StorageConfigPanel: configPanel template not found");
					return null;
				}
				string[] array = new string[5] { "Additive1", "Additive2", "Additive3", "Botanist", "ObjectFieldUI" };
				foreach (string text in array)
				{
					Transform val2 = val.transform.Find(text);
					if ((Object)(object)val2 != (Object)null)
					{
						Object.Destroy((Object)(object)((Component)val2).gameObject);
					}
				}
				Transform val3 = val.transform.Find("Seed");
				if ((Object)(object)val3 == (Object)null)
				{
					if (DebugLogs.All || DebugLogs.Storage)
					{
						MelonLogger.Error("StorageConfigPanel: itemFieldUITransform template not found");
					}
					return null;
				}
				GameObject gameObject = ((Component)val3).gameObject;
				((Object)gameObject).name = "StorageItemUI";
				if (!Object.op_Implicit((Object)(object)gameObject.GetComponent<CanvasRenderer>()))
				{
					gameObject.AddComponent<CanvasRenderer>();
				}
				TextMeshProUGUI val4 = ((IEnumerable<TextMeshProUGUI>)gameObject.GetComponentsInChildren<TextMeshProUGUI>()).FirstOrDefault((Func<TextMeshProUGUI, bool>)((TextMeshProUGUI t) => ((Object)((Component)t).gameObject).name == "Title"));
				if ((Object)(object)val4 != (Object)null)
				{
					((TMP_Text)val4).text = "Assign Item";
				}
				TextMeshProUGUI val5 = ((IEnumerable<TextMeshProUGUI>)gameObject.GetComponentsInChildren<TextMeshProUGUI>()).FirstOrDefault((Func<TextMeshProUGUI, bool>)((TextMeshProUGUI t) => ((Object)((Component)t).gameObject).name == "Description"));
				if ((Object)(object)val5 != (Object)null)
				{
					((TMP_Text)val5).text = "Select the item to assign to this shelf";
				}
				else if (DebugLogs.All || DebugLogs.Storage)
				{
					MelonLogger.Warning("StorageConfigPanel: Description TextMeshProUGUI missing");
				}
				ConfigPanelTemplate = storageConfigPanel;
				if (DebugLogs.All || DebugLogs.Storage)
				{
					MelonLogger.Msg("StorageConfigPanel: Template initialized successfully");
				}
				return storageConfigPanel;
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"StorageConfigPanel: Failed to initialize template, error: {arg}");
				return null;
			}
		}
	}
	public class ConfigurableStorageEntity : PlaceableStorageEntity, IConfigurable
	{
		[CompilerGenerated]
		private sealed class <>c__DisplayClass35_0
		{
			public ConfigurableStorageEntity <>4__this;

			public NetworkConnection conn;

			internal bool <SendConfigurationToClient>b__1()
			{
				return <>4__this.Configuration != null;
			}
		}

		public StorageConfiguration configuration;

		public ConfigurationReplicator configReplicator;

		public EntityConfiguration Configuration => (EntityConfiguration)(object)configuration;

		public ConfigurationReplicator ConfigReplicator => configReplicator;

		public EConfigurableType ConfigurableType => (EConfigurableType)345543;

		public WorldspaceUIElement WorldspaceUI { get; set; }

		public NetworkObject CurrentPlayerConfigurer { get; set; }

		public bool IsBeingConfiguredByOtherPlayer => (Object)(object)CurrentPlayerConfigurer != (Object)null && !CurrentPlayerConfigurer.IsOwner;

		public Sprite TypeIcon => null;

		public Transform Transform => ((Component)this).transform;

		public Transform UIPoint => ((Component)this).transform;

		public bool CanBeSelected => true;

		public override void InitializeGridItem(ItemInstance instance, Grid grid, Vector2 originCoordinate, int rotation, string GUID)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			bool initialized = ((BuildableItem)this).Initialized;
			((GridItem)this).InitializeGridItem(instance, grid, originCoordinate, rotation, GUID);
			if (!initialized && !((BuildableItem)this).isGhost)
			{
				if ((Object)(object)configReplicator == (Object)null)
				{
					configReplicator = ((Component)this).gameObject.AddComponent<ConfigurationReplicator>();
				}
				((BuildableItem)this).ParentProperty.AddConfigurable((IConfigurable)(object)this);
				configuration = new StorageConfiguration(configReplicator, (IConfigurable)(object)this, this);
				if (DebugLogs.All || DebugLogs.Storage)
				{
					MelonLogger.Msg("ConfigurableStorageEntity: Initialized configuration for " + ((Object)this).name);
				}
			}
		}

		public void SetConfigurer(NetworkObject player)
		{
			CurrentPlayerConfigurer = player;
			if (DebugLogs.All || DebugLogs.Storage)
			{
				MelonLogger.Msg("ConfigurableStorageEntity: Configurer set to " + (((player != null) ? ((Object)player).name : null) ?? "null") + " for " + ((Object)this).name);
			}
		}

		public void Selected()
		{
			EntityConfiguration obj = Configuration;
			if (obj != null)
			{
				obj.Selected();
			}
		}

		public void Deselected()
		{
			EntityConfiguration obj = Configuration;
			if (obj != null)
			{
				obj.Deselected();
			}
		}

		public override void DestroyItem(bool callOnServer = true)
		{
			if (configuration != null)
			{
				((EntityConfiguration)configuration).Destroy();
				((BuildableItem)this).ParentProperty.RemoveConfigurable((IConfigurable)(object)this);
				StorageExtensions.StorageConfig.Remove(((BuildableItem)this).GUID);
			}
			DestroyWorldspaceUI();
			((GridItem)this).DestroyItem(callOnServer);
		}

		public override List<string> WriteData(string parentFolderPath)
		{
			try
			{
				List<string> list = ((BuildableItem)this).WriteData(parentFolderPath);
				if (StorageExtensions.StorageConfig.TryGetValue(((BuildableItem)this).GUID, out var value) && ((EntityConfiguration)value).ShouldSave())
				{
					list.Add("Configuration.json");
					File.WriteAllText(Path.Combine(parentFolderPath, "Configuration.json"), ((EntityConfiguration)value).GetSaveString());
				}
				return list;
			}
			catch (Exception arg)
			{
				MelonLogger.Error(string.Format("ConfigurableStorageEntityWriteDataPatch: Failed for {0}, error: {1}", ((Object)this).name ?? "null", arg));
				return new List<string>();
			}
		}

		public WorldspaceUIElement CreateWorldspaceUI()
		{
			return null;
		}

		public void DestroyWorldspaceUI()
		{
			if ((Object)(object)WorldspaceUI != (Object)null)
			{
				WorldspaceUI.Destroy();
				WorldspaceUI = null;
			}
		}

		public override void OnSpawnServer(NetworkConnection connection)
		{
			((BuildableItem)this).OnSpawnServer(connection);
			if (!connection.IsLocalClient && ((BuildableItem)this).Initialized)
			{
				((BuildableItem)this).SendInitToClient(connection);
			}
			SendConfigurationToClient(connection);
		}

		public void SendConfigurationToClient(NetworkConnection conn)
		{
			<>c__DisplayClass35_0 CS$<>8__locals0 = new <>c__DisplayClass35_0();
			CS$<>8__locals0.<>4__this = this;
			CS$<>8__locals0.conn = conn;
			if (!CS$<>8__locals0.conn.IsHost)
			{
				((MonoBehaviour)Singleton<CoroutineService>.Instance).StartCoroutine(WaitForConfig());
			}
			[IteratorStateMachine(typeof(<>c__DisplayClass35_0.<<SendConfigurationToClient>g__WaitForConfig|0>d))]
			IEnumerator WaitForConfig()
			{
				//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
				return new <>c__DisplayClass35_0.<<SendConfigurationToClient>g__WaitForConfig|0>d(0)
				{
					<>4__this = CS$<>8__locals0
				};
			}
		}
	}
	public class StorageConfiguration : EntityConfiguration
	{
		public ItemField StorageItem { get; private set; }

		public ConfigurableStorageEntity Storage { get; private set; }

		public event Action OnChanged;

		public StorageConfiguration(ConfigurationReplicator replicator, IConfigurable configurable, ConfigurableStorageEntity storage)
			: base(replicator, configurable)
		{
			//IL_0014: Unknown result type (might be due to invalid IL or missing references)
			//IL_0019: 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_0030: Expected O, but got Unknown
			Storage = storage;
			StorageItem = new ItemField((EntityConfiguration)(object)this)
			{
				CanSelectNone = true,
				Options = new List<ItemDefinition>()
			};
			StorageItem.onItemChanged.AddListener((UnityAction<ItemDefinition>)delegate
			{
				((EntityConfiguration)this).InvokeChanged();
			});
			StorageExtensions.StorageConfig[((BuildableItem)storage).GUID] = this;
			if (DebugLogs.All || DebugLogs.Storage)
			{
				MelonLogger.Msg($"StorageConfiguration: Created for storage: {((BuildableItem)storage).GUID}");
			}
		}

		public override bool ShouldSave()
		{
			return StorageItem != null;
		}

		public override string GetSaveString()
		{
			//IL_0002: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Unknown result type (might be due to invalid IL or missing references)
			//IL_0024: Expected O, but got Unknown
			try
			{
				JObject val = new JObject { ["StorageItem"] = (JToken)(object)JObject.FromObject((object)StorageItem.GetData()) };
				string text = ((JToken)val).ToString((Formatting)1, Array.Empty<JsonConverter>());
				if (DebugLogs.All || DebugLogs.Storage)
				{
					MelonLogger.Msg("StorageConfiguration: Saved JSON: " + text);
				}
				return text;
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"StorageConfiguration: GetSaveString failed, error: {arg}");
				return "";
			}
		}
	}
	public class StorageConfigPanel : ConfigPanel
	{
		private ItemFieldUI storageItemUI;

		public override void Bind(List<EntityConfiguration> configs)
		{
			try
			{
				if (DebugLogs.All || DebugLogs.Storage)
				{
					MelonLogger.Msg($"StorageConfigPanel: Binding configs, count: {configs?.Count ?? 0}");
				}
				if ((Object)(object)this == (Object)null || (Object)(object)((Component)this).gameObject == (Object)null)
				{
					MelonLogger.Error("StorageConfigPanel: Instance or GameObject is null");
					return;
				}
				List<ItemField> list = new List<ItemField>();
				foreach (StorageConfiguration item in configs.OfType<StorageConfiguration>())
				{
					list.Add(item.StorageItem);
				}
				storageItemUI.Bind(list);
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"StorageConfigPanel: Bind failed, error: {arg}");
			}
		}
	}
	public class StoragePreset : Preset
	{
		private static StoragePreset DefaultPresetInstance;

		public ItemList StorageItem { get; set; }

		public string PresetDescription { get; set; }

		public override Preset GetCopy()
		{
			StoragePreset storagePreset = new StoragePreset();
			((Preset)this).CopyTo((Preset)(object)storagePreset);
			return (Preset)(object)storagePreset;
		}

		public override void CopyTo(Preset other)
		{
			//IL_0037: 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_004d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Expected O, but got Unknown
			((Preset)this).CopyTo(other);
			if (other is StoragePreset storagePreset)
			{
				storagePreset.StorageItem = new ItemList(((Option)StorageItem).Name, new List<string>(StorageItem.OptionList), false, true)
				{
					All = StorageItem.All,
					None = StorageItem.None
				};
				storagePreset.PresetDescription = PresetDescription;
			}
		}

		public override void InitializeOptions()
		{
			//IL_000e: 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)
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			//IL_0026: Expected O, but got Unknown
			StorageItem = new ItemList("Assign Item", new List<string>(), true, true)
			{
				All = false,
				None = true
			};
			PresetDescription = "Configures the item stored in the rack.";
		}

		public static StoragePreset GetDefaultPreset()
		{
			//IL_0024: Unknown result type (might be due to invalid IL or missing references)
			//IL_003e: Unknown result type (might be due to invalid IL or missing references)
			//IL_0043: Unknown result type (might be due to invalid IL or missing references)
			if (DefaultPresetInstance == null)
			{
				DefaultPresetInstance = new StoragePreset
				{
					PresetName = "Default",
					ObjectType = (ManageableObjectType)200,
					PresetColor = new Color32((byte)180, (byte)180, (byte)180, byte.MaxValue)
				};
				((Preset)DefaultPresetInstance).InitializeOptions();
			}
			return DefaultPresetInstance;
		}

		public static StoragePreset GetNewBlankPreset()
		{
			StoragePreset storagePreset = ((Preset)GetDefaultPreset()).GetCopy() as StoragePreset;
			((Preset)storagePreset).PresetName = "New Preset";
			return storagePreset;
		}
	}
	public class StoragePresetEditScreen : PresetEditScreen
	{
		private StoragePreset castedPreset;

		public GenericOptionUI StorageItemUI { get; set; }

		public override void Awake()
		{
			//IL_0046: Unknown result type (might be due to invalid IL or missing references)
			//IL_0050: Expected O, but got Unknown
			((PresetEditScreen)this).Awake();
			if ((Object)(object)StorageItemUI != (Object)null && (Object)(object)StorageItemUI.Button != (Object)null)
			{
				((UnityEvent)StorageItemUI.Button.onClick).AddListener((UnityAction)delegate
				{
					StorageItemUIClicked();
				});
			}
		}

		protected virtual void Update()
		{
			if (((PresetEditScreen)this).isOpen)
			{
				UpdateUI();
			}
		}

		public override void Open(Preset preset)
		{
			((PresetEditScreen)this).Open(preset);
			castedPreset = (StoragePreset)(object)base.EditedPreset;
			UpdateUI();
		}

		private void UpdateUI()
		{
			try
			{
				if (castedPreset != null && castedPreset.StorageItem != null && (Object)(object)StorageItemUI != (Object)null)
				{
					((TMP_Text)StorageItemUI.ValueLabel).text = ((Option)castedPreset.StorageItem).GetDisplayString();
					TextMeshProUGUI val = ((IEnumerable<TextMeshProUGUI>)((Component)this).GetComponentsInChildren<TextMeshProUGUI>(true)).FirstOrDefault((Func<TextMeshProUGUI, bool>)((TextMeshProUGUI t) => ((Object)((Component)t).gameObject).name == "Description"));
					if ((Object)(object)val != (Object)null)
					{
						((TMP_Text)val).text = castedPreset.PresetDescription ?? "";
					}
					else
					{
						MelonLogger.Warning("StoragePresetEditScreen: Description TextMeshProUGUI missing");
					}
				}
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"StoragePresetEditScreenUpdateUIPatch: Failed, error: {arg}");
			}
		}

		private void StorageItemUIClicked()
		{
			if (castedPreset == null)
			{
				MelonLogger.Error("StoragePresetEditScreen: Null preset");
				return;
			}
			List<string> optionList = new List<string>();
			castedPreset.StorageItem.OptionList = optionList;
			Singleton<ItemSetterScreen>.Instance.Open(castedPreset.StorageItem);
		}
	}
	[HarmonyPatch(typeof(StorageRackLoader), "Load")]
	public class StorageRackLoaderLoadPatch
	{
		private static void Postfix(StorageRackLoader __instance, string mainPath)
		{
			try
			{
				if (DebugLogs.All || DebugLogs.MixingStation)
				{
					MelonLogger.Msg("MixingStationLoaderPatch: Processing Postfix for mainPath: " + mainPath);
				}
				if (!GridItemLoaderPatch.LoadedGridItems.TryGetValue(mainPath, out var value) || (Object)(object)value == (Object)null)
				{
					if (DebugLogs.All || DebugLogs.MixingStation)
					{
						MelonLogger.Warning("MixingStationLoaderPatch: No GridItem found for mainPath: " + mainPath);
					}
				}
				else
				{
					if (!(value is ConfigurableStorageEntity configurableStorageEntity))
					{
						return;
					}
					string path = Path.Combine(mainPath, "Configuration.json");
					if (!File.Exists(path))
					{
						return;
					}
					string text = File.ReadAllText(path);
					JObject val = JObject.Parse(text);
					JToken val2 = val["StorageItem"];
					if (val2 != null && StorageExtensions.StorageConfig.TryGetValue(((BuildableItem)configurableStorageEntity).GUID, out var value2))
					{
						ItemField storageItem = value2.StorageItem;
						storageItem.Load(JsonUtility.FromJson<ItemFieldData>(((object)val2).ToString()));
						if (DebugLogs.All || DebugLogs.Storage)
						{
							MelonLogger.Msg("StorageRackLoaderLoadPatch: Loaded StorageItem for " + ((Object)configurableStorageEntity).name);
						}
					}
				}
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"StorageRackLoaderLoadPatch: Failed for {mainPath}, error: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(ConfigurableType), "GetTypeName")]
	public class ConfigurableTypeGetTypeNamePatch
	{
		private static bool Prefix(EConfigurableType type, ref string __result)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)type == 345543)
			{
				__result = "Storage Rack";
				if (DebugLogs.All || DebugLogs.Storage)
				{
					MelonLogger.Msg("ConfigurableType GetTypeNamePrefix: Returned StorageConfigPanel for StorageEnum");
				}
				return false;
			}
			return true;
		}
	}
	[HarmonyPatch(typeof(ManagementInterface), "GetConfigPanelPrefab")]
	public class ManagementInterfaceGetConfigPanelPrefabPatch
	{
		private static bool Prefix(EConfigurableType type, ref ConfigPanel __result)
		{
			//IL_0001: Unknown result type (might be due to invalid IL or missing references)
			//IL_0007: Invalid comparison between Unknown and I4
			if ((int)type == 345543)
			{
				__result = (ConfigPanel)(object)StorageExtensions.GetStorageConfigPanelTemplate();
				if (DebugLogs.All || DebugLogs.Storage)
				{
					MelonLogger.Msg("ManagementInterface GetConfigPanelPrefabPatch: Returned StorageConfigPanel for StorageEnum");
				}
				return false;
			}
			return true;
		}
	}
}
namespace NoLazyWorkers.Chemists
{
	public static class CauldronExtensions
	{
		public static Dictionary<Guid, ObjectField> Supply = new Dictionary<Guid, ObjectField>();

		public static Dictionary<Guid, CauldronConfiguration> CauldronConfig = new Dictionary<Guid, CauldronConfiguration>();

		public static Dictionary<Guid, TransitRoute> SupplyRoute = new Dictionary<Guid, TransitRoute>();
	}
	public static class ChemistExtensions
	{
		public static ItemField GetMixerItemForProductSlot(MixingStation station)
		{
			if ((Object)(object)station == (Object)null)
			{
				if (DebugLogs.All || DebugLogs.MixingStation)
				{
					MelonLogger.Warning($"GetMixerItemForProductSlot: Product slot item is not a ProductDefinition for station={((station != null) ? new Guid?(((BuildableItem)station).GUID) : null)}");
				}
				return null;
			}
			ItemInstance itemInstance = station.ProductSlot.ItemInstance;
			ProductDefinition productInSlot = default(ProductDefinition);
			ref ProductDefinition reference = ref productInSlot;
			ItemDefinition obj = ((itemInstance != null) ? itemInstance.Definition : null);
			reference = (ProductDefinition)(object)((obj is ProductDefinition) ? obj : null);
			if ((Object)(object)productInSlot == (Object)null)
			{
				if (DebugLogs.All || DebugLogs.MixingStation)
				{
					ItemInstance itemInstance2 = station.ProductSlot.ItemInstance;
					MelonLogger.Warning($"GetMixerItemForProductSlot: Product slot {((itemInstance2 != null) ? itemInstance2.Definition : null)} item is not a ProductDefinition for station={((station != null) ? new Guid?(((BuildableItem)station).GUID) : null)}");
				}
				return null;
			}
			if (!MixingStationExtensions.MixingRoutes.TryGetValue(((BuildableItem)station).GUID, out var value) || value == null || value.Count == 0)
			{
				if (DebugLogs.All || DebugLogs.MixingStation)
				{
					MelonLogger.Msg($"GetMixerItemForProductSlot: No routes defined for station={((BuildableItem)station).GUID}");
				}
				return null;
			}
			MixingRoute mixingRoute = value.FirstOrDefault(delegate(MixingRoute route)
			{
				ItemField product = route.Product;
				return (Object)(object)((product != null) ? product.SelectedItem : null) != (Object)null && (Object)(object)route.Product.SelectedItem == (Object)(object)productInSlot;
			});
			if (mixingRoute == null)
			{
				if (DebugLogs.All || DebugLogs.MixingStation)
				{
					MelonLogger.Msg($"GetMixerItemForProductSlot: No route matches product={((ItemDefinition)productInSlot).Name} for station={((BuildableItem)station).GUID}");
				}
				return null;
			}
			if (DebugLogs.All || DebugLogs.MixingStation)
			{
				MelonLogger.Msg(string.Format("GetMixerItemForProductSlot: Found mixerItem={0} for product={1} in station={2}", mixingRoute.MixerItem.SelectedItem?.Name ?? "null", ((ItemDefinition)productInSlot).Name, ((BuildableItem)station).GUID));
			}
			return mixingRoute.MixerItem;
		}

		public static ItemInstance GetItemInSupply(this Chemist chemist, MixingStation station, string id)
		{
			ObjectField val = MixingStationExtensions.Supply[((BuildableItem)station).GUID];
			List<ItemSlot> list = new List<ItemSlot>();
			BuildableItem selectedObject = val.SelectedObject;
			if ((Object)(object)selectedObject != (Object)null && ((NPC)chemist).behaviour.Npc.Movement.CanGetTo((ITransitEntity)(object)((selectedObject is ITransitEntity) ? selectedObject : null), 1f))
			{
				list.AddRange(((ITransitEntity)((selectedObject is ITransitEntity) ? selectedObject : null)).OutputSlots);
				for (int i = 0; i < list.Count; i++)
				{
					if (list[i].Quantity > 0 && list[i].ItemInstance.ID.ToLower() == id.ToLower())
					{
						return list[i].ItemInstance;
					}
				}
			}
			return null;
		}
	}
	[HarmonyPatch(typeof(Chemist))]
	public class ChemistPatch
	{
		[HarmonyPatch("GetMixingStationsReadyToStart")]
		[HarmonyPrefix]
		private static bool Prefix(Chemist __instance, ref List<MixingStation> __result)
		{
			try
			{
				List<MixingStation> list = new List<MixingStation>();
				if (DebugLogs.All || DebugLogs.Chemist)
				{
					MelonLogger.Msg(string.Format("ChemistPatch.GetMixingStationsReadyToStart: Checking stations for {0}, total stations={1}", ((__instance != null) ? ((Object)__instance).name : null) ?? "null", __instance.configuration.MixStations.Count));
				}
				foreach (MixingStation mixStation in __instance.configuration.MixStations)
				{
					if (((IUsable)mixStation).IsInUse || mixStation.CurrentMixOperation != null)
					{
						continue;
					}
					if (!MixingStationExtensions.Config.TryGetValue(((BuildableItem)mixStation).GUID, out var value))
					{
						if (DebugLogs.All || DebugLogs.Chemist)
						{
							MelonLogger.Warning($"ChemistPatch.GetMixingStationsReadyToStart: MixerConfig missing for station {((mixStation != null) ? new Guid?(((BuildableItem)mixStation).GUID) : null)}");
						}
						EntityConfiguration configuration = mixStation.Configuration;
						value = (MixingStationConfiguration)(object)((configuration is MixingStationConfiguration) ? configuration : null);
						MixingStationExtensions.Config[((BuildableItem)mixStation).GUID] = value;
					}
					ItemField mixerItemForProductSlot = ChemistExtensions.GetMixerItemForProductSlot(mixStation);
					if ((Object)(object)((mixerItemForProductSlot != null) ? mixerItemForProductSlot.SelectedItem : null) == (Object)null)
					{
						continue;
					}
					float value2 = value.StartThrehold.Value;
					int mixQuantity = mixStation.GetMixQuantity();
					bool flag = (float)mixQuantity >= value2 && (float)mixStation.ProductSlot.Quantity >= value2 && mixStation.OutputSlot.Quantity == 0;
					bool flag2 = false;
					bool flag3 = false;
					ObjectField val = MixingStationExtensions.Supply[((BuildableItem)mixStation).GUID];
					if (!flag && (Object)(object)val?.SelectedObject != (Object)null)
					{
						ConfigurationExtensions.NPCSupply[((NPC)__instance).GUID] = val;
						object obj;
						if (mixerItemForProductSlot == null)
						{
							obj = null;
						}
						else
						{
							ItemDefinition selectedItem = mixerItemForProductSlot.SelectedItem;
							obj = ((selectedItem != null) ? selectedItem.GetDefaultInstance(1) : null);
						}
						ItemInstance item = (ItemInstance)obj;
						if ((Object)(object)mixerItemForProductSlot.SelectedItem != (Object)null)
						{
							item = mixerItemForProductSlot.SelectedItem.GetDefaultInstance(1);
						}
						flag3 = HasSufficientItems(__instance, value2, item);
						flag2 = mixStation.OutputSlot.Quantity == 0 && (float)mixStation.ProductSlot.Quantity >= value2 && flag3;
					}
					if (DebugLogs.All || DebugLogs.Chemist)
					{
						object[] obj2 = new object[12]
						{
							((BuildableItem)mixStation).GUID,
							null,
							null,
							null,
							null,
							null,
							null,
							null,
							null,
							null,
							null,
							null
						};
						Guid? obj3;
						if (val == null)
						{
							obj3 = null;
						}
						else
						{
							BuildableItem selectedObject = val.SelectedObject;
							obj3 = ((selectedObject != null) ? new Guid?(selectedObject.GUID) : null);
						}
						obj2[1] = obj3;
						obj2[2] = ((Component)mixStation).GetComponent<IUsable>().IsInUse;
						obj2[3] = mixStation.CurrentMixOperation != null;
						obj2[4] = flag;
						obj2[5] = flag2;
						obj2[6] = mixQuantity;
						obj2[7] = mixStation.ProductSlot.Quantity;
						obj2[8] = mixStation.OutputSlot.Quantity;
						obj2[9] = value2;
						obj2[10] = mixerItemForProductSlot.SelectedItem?.Name ?? "null";
						obj2[11] = (flag2 ? $", hasSufficientItems={flag3}" : "");
						MelonLogger.Msg(string.Format("ChemistPatch.GetMixingStationsReadyToStart: Station {0}, Supply={1}, IsInUse={2}, CurrentMixOperation={3}, canStartMix={4}, canRestock={5}, mixQuantity={6}, productQuantity={7}, outputQuantity={8}, threshold={9}, mixerItem={10}{11}", obj2));
					}
					if (flag || flag2)
					{
						list.Add(mixStation);
					}
				}
				__result = list;
				if (DebugLogs.All || DebugLogs.Chemist)
				{
					MelonLogger.Msg(string.Format("ChemistPatch.GetMixingStationsReadyToStart: Found {0} stations ready for {1}", list.Count, ((__instance != null) ? ((Object)__instance).name : null) ?? "null"));
				}
				return false;
			}
			catch (Exception arg)
			{
				MelonLogger.Error(string.Format("ChemistPatch.GetMixingStationsReadyToStart: Failed for chemist: {0}, error: {1}", ((__instance != null) ? ((Object)__instance).name : null) ?? "null", arg));
				__result = new List<MixingStation>();
				return false;
			}
		}

		public static ItemDefinition GetAnyMixer(ITransitEntity supply, float threshold, string preferredId = null)
		{
			if (supply == null || supply.OutputSlots == null)
			{
				if (DebugLogs.All || DebugLogs.Chemist)
				{
					MelonLogger.Warning("GetAnyMixer: Supply or OutputSlots is null");
				}
				return null;
			}
			List<PropertyItemDefinition> validItems = NetworkSingleton<ProductManager>.Instance.ValidMixIngredients;
			IEnumerable<ItemSlot> source = supply.OutputSlots.Where(delegate(ItemSlot s)
			{
				ItemSlot obj = s;
				return ((obj != null) ? obj.ItemInstance : null) != null && validItems.Any((PropertyItemDefinition v) => ((ItemDefinition)v).ID.ToLower() == s.ItemInstance.ID.ToLower()) && (float)s.Quantity >= threshold;
			});
			if (preferredId != null)
			{
				ItemSlot val = source.FirstOrDefault((Func<ItemSlot, bool>)((ItemSlot s) => s.ItemInstance.ID.ToLower() == preferredId.ToLower()));
				if (val != null)
				{
					if (DebugLogs.All || DebugLogs.Chemist)
					{
						MelonLogger.Msg($"GetAnyMixer: Selected preferred item {preferredId} with quantity={val.Quantity}");
					}
					return val.ItemInstance.definition;
				}
			}
			ItemSlot val2 = source.FirstOrDefault();
			if (val2 != null && (DebugLogs.All || DebugLogs.Chemist))
			{
				MelonLogger.Msg($"GetAnyMixer: Selected first available item {val2.ItemInstance.ID} with quantity={val2.Quantity}");
			}
			return (val2 == null) ? null : val2.ItemInstance?.definition;
		}

		public static bool HasSufficientItems(Chemist chemist, float threshold, ItemInstance item)
		{
			return (float)NoLazyUtilities.GetAmountInInventoryAndSupply((NPC)(object)chemist, item?.definition) >= threshold;
		}
	}
	[HarmonyPatch(typeof(ChemistConfiguration))]
	public class ChemistConfigurationPatch
	{
		[HarmonyPostfix]
		[HarmonyPatch(/*Could not decode attribute arguments.*/)]
		private static void Postfix(ChemistConfiguration __instance)
		{
			try
			{
				Chemist chemist = __instance.chemist;
			}
			catch (Exception arg)
			{
				MelonLogger.Error($"ChemistConfigurationPatch: Failed, error: {arg}");
			}
		}
	}
	[HarmonyPatch(typeof(StartMixingStationBehaviour))]
	public class StartMixingStationBehaviourPatch
	{
		private class StateData
		{
			public Coroutine WalkToSuppliesRoutine { get; set; }

			public Coroutine GrabRoutine { get; set; }

			public ItemDefinition TargetMixer { get; set; }

			public bool ClearMixerSlot { get; set; }

			public int QuantityToFetch { get; set; }

			public EState CurrentState { get; set; }

			public ObjectField LastSupply { get; set; }

			public bool CookPending { get; set; }

			public bool Any { get; set; }

			public float LastStateChangeTime { get; set; }
		}

		public enum EState
		{
			Idle,
			WalkingToSupplies,
			GrabbingSupplies,
			WalkingToStation,
			Cooking
		}

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

			private object <>2__current;

			public StartMixingStationBehaviour __instance;

			public StateData state;

			private Chemist <chemist>5__1;

			private MixingStation <station>5__2;

			private ItemField <mixerItem>5__3;

			private ObjectField <mixerSupply>5__4;

			private string <reason>5__5;

			private Exception <e>5__6;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<chemist>5__1 = null;
				<station>5__2 = null;
				<mixerItem>5__3 = null;
				<mixerSupply>5__4 = null;
				<reason>5__5 = null;
				<e>5__6 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_00f2: Unknown result type (might be due to invalid IL or missing references)
				//IL_00fc: Expected O, but got Unknown
				//IL_0314: Unknown result type (might be due to invalid IL or missing references)
				//IL_0263: Unknown result type (might be due to invalid IL or missing references)
				//IL_026d: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<chemist>5__1 = __instance.chemist;
					<station>5__2 = __instance.targetStation;
					<mixerItem>5__3 = ChemistExtensions.GetMixerItemForProductSlot(<station>5__2);
					<mixerSupply>5__4 = MixingStationExtensions.Supply[((BuildableItem)<station>5__2).GUID];
					if (!IsStationValid(__instance, <station>5__2, <mixerItem>5__3, <mixerSupply>5__4, <chemist>5__1, out <reason>5__5))
					{
						if (DebugLogs.All || DebugLogs.Chemist)
						{
							MelonLogger.Msg("StartMixingStationBehaviourPatch.GrabRoutine: Station invalid before grab (reason=" + <reason>5__5 + "), disabling");
						}
						Disable(__instance);
						return false;
					}
					<>2__current = (object)new WaitForSeconds(0.1f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					try
					{
						if ((Object)(object)((NPC)<chemist>5__1).Avatar?.Anim != (Object)null)
						{
							((NPC)<chemist>5__1).Avatar.Anim.ResetTrigger("GrabItem");
							((NPC)<chemist>5__1).Avatar.Anim.SetTrigger("GrabItem");
							if (DebugLogs.All || DebugLogs.Chemist)
							{
								Chemist obj2 = <chemist>5__1;
								MelonLogger.Msg("StartMixingStationBehaviourPatch.GrabRoutine: Triggered GrabItem animation for " + ((obj2 != null) ? ((NPC)obj2).fullName : null));
							}
						}
						else if (DebugLogs.All || DebugLogs.Chemist)
						{
							Chemist obj3 = <chemist>5__1;
							MelonLogger.Warning("StartMixingStationBehaviourPatch.GrabRoutine: Animator missing for " + ((obj3 != null) ? ((NPC)obj3).fullName : null) + ", skipping animation");
						}
					}
					catch (Exception ex)
					{
						<e>5__6 = ex;
						Chemist obj4 = <chemist>5__1;
						MelonLogger.Error($"StartMixingStationBehaviourPatch.GrabRoutine: Failed for {((obj4 != null) ? ((NPC)obj4).fullName : null)}, error: {<e>5__6}");
						Disable(__instance);
						if (DebugLogs.All || DebugLogs.Chemist)
						{
							Chemist obj5 = <chemist>5__1;
							MelonLogger.Warning("StartMixingStationBehaviourPatch.GrabRoutine: Reverted to Idle due to error for " + ((obj5 != null) ? ((NPC)obj5).fullName : null));
						}
						return false;
					}
					<>2__current = (object)new WaitForSeconds(0.1f);
					<>1__state = 2;
					return true;
				case 2:
					<>1__state = -1;
					if (!IsStationValid(__instance, <station>5__2, <mixerItem>5__3, <mixerSupply>5__4, <chemist>5__1, out <reason>5__5))
					{
						if (DebugLogs.All || DebugLogs.Chemist)
						{
							MelonLogger.Msg("StartMixingStationBehaviourPatch.GrabRoutine: Station invalid after grab (reason=" + <reason>5__5 + "), disabling");
						}
						Disable(__instance);
						return false;
					}
					state.GrabRoutine = null;
					state.CurrentState = EState.WalkingToStation;
					((Behaviour)__instance).SetDestination(GetStationAccessPoint(__instance), true);
					if (DebugLogs.All || DebugLogs.Chemist)
					{
						Chemist obj = <chemist>5__1;
						MelonLogger.Msg($"StartMixingStationBehaviourPatch.GrabRoutine: Grab complete, walking to station for {((obj != null) ? ((NPC)obj).fullName : null)}, productQuantity={<station>5__2.ProductSlot.Quantity}");
					}
					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 <WalkRoutine>d__12 : IEnumerator<object>, IDisposable, IEnumerator
		{
			private int <>1__state;

			private object <>2__current;

			public StartMixingStationBehaviour __instance;

			public ITransitEntity supply;

			public StateData state;

			private Chemist <chemist>5__1;

			private MixingStation <station>5__2;

			private Vector3 <startPos>5__3;

			private float <timeout>5__4;

			private float <elapsed>5__5;

			private ItemField <mixerItem>5__6;

			private ObjectFi