Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of NoLazyWorkers v1.1.10
Mods/NoLazyWorkers.dll
Decompiled 2 months ago
The result has been truncated due to the large size, download it to view full contents!
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