Decompiled source of BetterChemStationsIl2cpp v1.2.2

BetterChemStationsIL2.dll

Decompiled a month ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using BetterChemStationsIL2;
using HarmonyLib;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppScheduleOne.ItemFramework;
using Il2CppScheduleOne.Management;
using Il2CppScheduleOne.ObjectScripts;
using Il2CppScheduleOne.StationFramework;
using Il2CppSystem.Collections.Generic;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(Core), "BetterChemStationsMain", "1.2.2", "trpip", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("BetterChemStationsIL2")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+2b17f22906a4130797751944bce7c814ad932b7b")]
[assembly: AssemblyProduct("BetterChemStationsIL2")]
[assembly: AssemblyTitle("BetterChemStationsIL2")]
[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 BetterChemStationsIL2
{
	public class Core : MelonMod
	{
		private static readonly string CATEGORY = "BetterChemStations";

		private static MelonPreferences_Entry<bool> _debugModeEntry;

		public static bool DebugMode => _debugModeEntry?.Value ?? false;

		public override void OnInitializeMelon()
		{
			MelonPreferences_Category val = MelonPreferences.CreateCategory(CATEGORY);
			_debugModeEntry = val.CreateEntry<bool>("DebugMode", false, "Debug Logging", "When enabled, outputs detailed logs to help with troubleshooting.", false, false, (ValueValidator)null, (string)null);
			Harmony.CreateAndPatchAll(typeof(RecipeChangedPatch), (string)null);
			Harmony.CreateAndPatchAll(typeof(ChemistryStationAwakePatch), (string)null);
			((MelonBase)this).LoggerInstance.Msg("Chemistry Station Filter Mod loaded!");
			DebugLog("Debug mode is enabled");
		}

		public static void DebugLog(string message)
		{
			if (DebugMode)
			{
				MelonLogger.Msg("[DEBUG] " + message);
			}
		}
	}
	public static class FilterHelper
	{
		[CompilerGenerated]
		private sealed class <DelayedFilterApplication>d__5 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public ChemistryStation station;

			public float delay;

			private ChemistryStationConfiguration <config>5__1;

			private StationRecipe <recipe>5__2;

			private Exception <ex>5__3;

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

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

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

			[DebuggerHidden]
			void IDisposable.Dispose()
			{
				<config>5__1 = null;
				<recipe>5__2 = null;
				<ex>5__3 = null;
				<>1__state = -2;
			}

			private bool MoveNext()
			{
				//IL_0089: Unknown result type (might be due to invalid IL or missing references)
				//IL_0093: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					Core.DebugLog($"Starting delayed filter application for {((Object)station).name} with delay {delay}s");
					<>2__current = (object)new WaitForSeconds(delay);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					Core.DebugLog($"Applying delayed filters for {((Object)station).name} after {delay}s");
					try
					{
						<config>5__1 = GetStationConfiguration(station);
						if (<config>5__1 == null)
						{
							Core.DebugLog("Config is still null after delay - recipe may not be set");
							return false;
						}
						StationRecipeField recipe = <config>5__1.Recipe;
						<recipe>5__2 = ((recipe != null) ? recipe.SelectedRecipe : null);
						if ((Object)(object)<recipe>5__2 != (Object)null && !IsGhost(station))
						{
							Core.DebugLog("Found recipe after delay: " + <recipe>5__2.RecipeTitle);
							ApplyRecipeFilters(station, <recipe>5__2);
						}
						else
						{
							Core.DebugLog("No recipe found after delay: recipe is " + (((Object)(object)<recipe>5__2 == (Object)null) ? "null" : "not null"));
						}
						<config>5__1 = null;
						<recipe>5__2 = null;
					}
					catch (Exception ex)
					{
						<ex>5__3 = ex;
						MelonLogger.Error("Error in delayed filter application: " + <ex>5__3.Message);
					}
					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();
			}
		}

		public static void ApplyRecipeFilters(ChemistryStation station, StationRecipe recipe)
		{
			//IL_015d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0162: Unknown result type (might be due to invalid IL or missing references)
			//IL_016f: Expected O, but got Unknown
			if ((Object)(object)station == (Object)null || ((recipe != null) ? recipe.Ingredients : null) == null)
			{
				MelonLogger.Warning("Cannot apply filters: station or recipe is null");
				return;
			}
			Core.DebugLog($"Applying filters for recipe: {recipe.RecipeTitle} with {recipe.Ingredients.Count} ingredients");
			try
			{
				for (int i = 0; i < ((Il2CppArrayBase<ItemSlot>)(object)station.IngredientSlots).Length; i++)
				{
					ItemSlot val = ((Il2CppArrayBase<ItemSlot>)(object)station.IngredientSlots)[i];
					if (((object)val).GetType().GetField("Filters", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(val) is List<ItemFilter> list)
					{
						list.Clear();
					}
				}
				for (int j = 0; j < recipe.Ingredients.Count && j < ((Il2CppArrayBase<ItemSlot>)(object)station.IngredientSlots).Length; j++)
				{
					IngredientQuantity val2 = recipe.Ingredients[j];
					ItemSlot val3 = ((Il2CppArrayBase<ItemSlot>)(object)station.IngredientSlots)[j];
					List<string> val4 = new List<string>();
					Enumerator<ItemDefinition> enumerator = val2.Items.GetEnumerator();
					while (enumerator.MoveNext())
					{
						ItemDefinition current = enumerator.Current;
						val4.Add(current.ID);
					}
					val3.AddFilter((ItemFilter)new ItemFilter_ID(val4)
					{
						IsWhitelist = true
					});
					Core.DebugLog($"Added filter for ingredient {val2.Item.Name} to slot {j}");
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Error applying filters: " + ex.Message);
			}
		}

		public static ChemistryStationConfiguration GetStationConfiguration(ChemistryStation station)
		{
			try
			{
				PropertyInfo propertyInfo = AccessTools.Property(typeof(ChemistryStation), "stationConfiguration");
				if (propertyInfo != null)
				{
					object? value = propertyInfo.GetValue(station);
					return (ChemistryStationConfiguration)((value is ChemistryStationConfiguration) ? value : null);
				}
				MelonLogger.Warning("Could not find stationConfiguration field");
				return null;
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Error accessing station configuration: " + ex.Message);
				return null;
			}
		}

		public static StationRecipe GetRecipeFromConfig(ChemistryStationConfiguration config)
		{
			if (config == null)
			{
				return null;
			}
			try
			{
				StationRecipeField recipe = config.Recipe;
				return (recipe != null) ? recipe.SelectedRecipe : null;
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Error getting recipe: " + ex.Message);
				return null;
			}
		}

		public static bool IsGhost(ChemistryStation station)
		{
			try
			{
				FieldInfo fieldInfo = AccessTools.Field(typeof(ChemistryStation), "isGhost");
				if (fieldInfo != null)
				{
					return (bool)fieldInfo.GetValue(station);
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Error checking isGhost: " + ex.Message);
			}
			return false;
		}

		public static void StartDelayedFilterApplication(ChemistryStation station, float delay)
		{
			MelonCoroutines.Start(DelayedFilterApplication(station, delay));
		}

		[IteratorStateMachine(typeof(<DelayedFilterApplication>d__5))]
		private static IEnumerator DelayedFilterApplication(ChemistryStation station, float delay)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <DelayedFilterApplication>d__5(0)
			{
				station = station,
				delay = delay
			};
		}
	}
	[HarmonyPatch(/*Could not decode attribute arguments.*/)]
	public class RecipeChangedPatch
	{
		private static void Postfix(ChemistryStationConfiguration __instance)
		{
			try
			{
				UnityAction<StationRecipe> val = UnityAction<StationRecipe>.op_Implicit((Action<StationRecipe>)delegate(StationRecipe recipe)
				{
					Core.DebugLog("Recipe changed to: " + (((recipe != null) ? recipe.RecipeTitle : null) ?? "null"));
					FilterHelper.ApplyRecipeFilters(__instance.Station, recipe);
				});
				__instance.Recipe.onRecipeChanged.AddListener(val);
				StationRecipeField recipe2 = __instance.Recipe;
				StationRecipe val2 = ((recipe2 != null) ? recipe2.SelectedRecipe : null);
				Core.DebugLog("Current recipe: " + (((val2 != null) ? val2.RecipeTitle : null) ?? "null"));
				if ((Object)(object)val2 != (Object)null && !FilterHelper.IsGhost(__instance.Station))
				{
					Core.DebugLog("Applying filters for initial recipe: " + val2.RecipeTitle);
					FilterHelper.ApplyRecipeFilters(__instance.Station, val2);
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Error in RecipeChangedPatch: " + ex.Message);
			}
		}
	}
	[HarmonyPatch(typeof(ChemistryStation), "Awake")]
	public class ChemistryStationAwakePatch
	{
		private static void Postfix(ChemistryStation __instance)
		{
			try
			{
				if (FilterHelper.IsGhost(__instance))
				{
					Core.DebugLog("Skipping Awake hook for ghost ChemistryStation " + ((Object)__instance).name);
					return;
				}
				Core.DebugLog("Awake called for ChemistryStation " + ((Object)__instance).name);
				ChemistryStationConfiguration stationConfiguration = FilterHelper.GetStationConfiguration(__instance);
				if (stationConfiguration != null)
				{
					Core.DebugLog("Found config in Awake, checking for recipe");
					StationRecipeField recipe = stationConfiguration.Recipe;
					StationRecipe val = ((recipe != null) ? recipe.SelectedRecipe : null);
					if ((Object)(object)val != (Object)null)
					{
						Core.DebugLog("Found recipe in Awake: " + val.RecipeTitle);
						FilterHelper.ApplyRecipeFilters(__instance, val);
					}
					else
					{
						Core.DebugLog("No recipe found in Awake, setting up delayed attempt");
						FilterHelper.StartDelayedFilterApplication(__instance, 2f);
					}
				}
				else
				{
					Core.DebugLog("Station configuration is null in Awake");
					FilterHelper.StartDelayedFilterApplication(__instance, 3f);
				}
			}
			catch (Exception ex)
			{
				MelonLogger.Error("Error in ChemistryStationAwakePatch: " + ex.Message);
			}
		}
	}
}