Decompiled source of Lithium fork v1.0.9

Lithium_fork.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Emit;
using System.Resources;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using System.Text;
using System.Text.RegularExpressions;
using HarmonyLib;
using Il2CppFishNet;
using Il2CppFishNet.Object;
using Il2CppInterop.Runtime.Injection;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppScheduleOne;
using Il2CppScheduleOne.Core.Items.Framework;
using Il2CppScheduleOne.DevUtilities;
using Il2CppScheduleOne.Dialogue;
using Il2CppScheduleOne.Economy;
using Il2CppScheduleOne.Effects;
using Il2CppScheduleOne.Employees;
using Il2CppScheduleOne.Equipping;
using Il2CppScheduleOne.GameTime;
using Il2CppScheduleOne.Growing;
using Il2CppScheduleOne.ItemFramework;
using Il2CppScheduleOne.Law;
using Il2CppScheduleOne.Levelling;
using Il2CppScheduleOne.Management;
using Il2CppScheduleOne.Messaging;
using Il2CppScheduleOne.Money;
using Il2CppScheduleOne.NPCs;
using Il2CppScheduleOne.NPCs.Behaviour;
using Il2CppScheduleOne.NPCs.CharacterClasses;
using Il2CppScheduleOne.ObjectScripts;
using Il2CppScheduleOne.PlayerScripts;
using Il2CppScheduleOne.Product;
using Il2CppScheduleOne.Property;
using Il2CppScheduleOne.Quests;
using Il2CppScheduleOne.StationFramework;
using Il2CppScheduleOne.UI;
using Il2CppScheduleOne.UI.Handover;
using Il2CppScheduleOne.UI.Items;
using Il2CppScheduleOne.UI.Phone;
using Il2CppScheduleOne.UI.Phone.Delivery;
using Il2CppScheduleOne.UI.Phone.Messages;
using Il2CppScheduleOne.UI.Shop;
using Il2CppScheduleOne.UI.Stations;
using Il2CppScheduleOne.UI.Stations.Drying_rack;
using Il2CppScheduleOne.Variables;
using Il2CppSystem.Collections.Generic;
using Il2CppTMPro;
using Lithium;
using Lithium.Helper;
using Lithium.Modules;
using Lithium.Modules.CauldronCustom;
using Lithium.Modules.ChemistryStation;
using Lithium.Modules.Customers;
using Lithium.Modules.Customers.Architecture;
using Lithium.Modules.Customers.Behaviours;
using Lithium.Modules.Customers.BonusPayments;
using Lithium.Modules.DryingRacks;
using Lithium.Modules.DynamicsOrders;
using Lithium.Modules.EffectCombos;
using Lithium.Modules.EffectCombos.BonusPayments;
using Lithium.Modules.Employees;
using Lithium.Modules.Employees.Patches;
using Lithium.Modules.LabOven;
using Lithium.Modules.MixingStations;
using Lithium.Modules.MixingStations.Patches;
using Lithium.Modules.PlantGrowth;
using Lithium.Modules.PlantGrowth.Behaviours;
using Lithium.Modules.PlantGrowth.Patches;
using Lithium.Modules.PropertyPrices;
using Lithium.Modules.Shops;
using Lithium.Modules.Shops.Patches;
using Lithium.Modules.StackSizes;
using Lithium.Modules.Storyline;
using Lithium.Modules.TrashGrabber;
using Lithium.Modules.WateringCans;
using Lithium.Util;
using MelonLoader;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Core), "Lithium_fork", "1.1.1", "DerTomDerTwitch (original Lithium) & fork maintainer", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: MelonPlatformDomain(/*Could not decode attribute arguments.*/)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("Lithium_fork")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.1.1.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("Lithium_fork")]
[assembly: AssemblyTitle("Lithium_fork")]
[assembly: NeutralResourcesLanguage("en-US")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.1.1.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.Class | AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Event | AttributeTargets.Parameter | AttributeTargets.ReturnValue | AttributeTargets.GenericParameter, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableAttribute : Attribute
	{
		public readonly byte[] NullableFlags;

		public NullableAttribute(byte P_0)
		{
			NullableFlags = new byte[1] { P_0 };
		}

		public NullableAttribute(byte[] P_0)
		{
			NullableFlags = P_0;
		}
	}
	[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 Lithium
{
	public class Core : MelonMod
	{
		public static readonly List<ModuleBase> Modules = new List<ModuleBase>(16)
		{
			new ModPropertyPrices(),
			new ModPlants(),
			new ModDryingRacks(),
			new ModCustomers(),
			new ModDynamicsOrders(),
			new ModStackSizes(),
			new ModLabOven(),
			new ModTrashGrabber(),
			new ModMixingStations(),
			new ModStoryline(),
			new ModShops(),
			new ModEmployees(),
			new ModCauldronCustom(),
			new ModChemistryStation(),
			new ModWateringCan(),
			new ModEffectCombos()
		};

		private const string ForkCredit = "Lithium_fork: fork maintained for Schedule I updates. Original mod \"Lithium\" by DerTomDerTwitch; development continued here due to lack of time on the author's side.";

		private bool _isFirstStart = true;

		public static Instance Logger { get; set; }

		public static T Get<T>() where T : ModuleBase
		{
			return Modules.OfType<T>().FirstOrDefault();
		}

		public override void OnInitializeMelon()
		{
			//IL_00cd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d3: Expected O, but got Unknown
			Logger = ((MelonBase)this).LoggerInstance;
			((MelonBase)this).LoggerInstance.Msg("Lithium_fork: fork maintained for Schedule I updates. Original mod \"Lithium\" by DerTomDerTwitch; development continued here due to lack of time on the author's side.");
			foreach (ModuleBase module in Modules)
			{
				try
				{
					((MelonBase)this).LoggerInstance.Msg("Loading " + module.GetType().Name);
					module.Load();
				}
				catch (Exception value)
				{
					((MelonBase)this).LoggerInstance.Error($"Failed to load module {module.GetType().Name}: {value}");
				}
			}
			Harmony val = new Harmony("com.lithium_fork");
			try
			{
				val.PatchAll();
			}
			catch (Exception value2)
			{
				((MelonBase)this).LoggerInstance.Error($"Harmony PatchAll failed: {value2}");
			}
			finally
			{
				try
				{
					BotanistDynamicTimingPatches.Register(val);
				}
				catch (Exception value3)
				{
					((MelonBase)this).LoggerInstance.Error($"BotanistDynamicTimingPatches.Register failed: {value3}");
				}
				try
				{
					GrowContainerShroomHarmony.Apply(val);
				}
				catch (Exception value4)
				{
					((MelonBase)this).LoggerInstance.Error($"GrowContainerShroomHarmony.Apply failed: {value4}");
				}
			}
			((MelonBase)this).LoggerInstance.Msg("Lithium_fork initialized");
		}

		public override void OnSceneWasInitialized(int buildIndex, string sceneName)
		{
			if (sceneName == "Main")
			{
				foreach (ModuleBase module in Modules)
				{
					try
					{
						((MelonBase)this).LoggerInstance.Msg("Apply " + module.GetType().Name);
						module.Apply();
					}
					catch (Exception value)
					{
						((MelonBase)this).LoggerInstance.Error($"Failed to apply module {module.GetType().Name}: {value}");
					}
				}
				_isFirstStart = false;
			}
			else if (sceneName.Equals("Menu", StringComparison.OrdinalIgnoreCase))
			{
				SupplierStartPatch.ClearListingStockCache();
				if (!_isFirstStart)
				{
					_isFirstStart = true;
				}
			}
		}

		public override void OnUpdate()
		{
			((MelonBase)this).OnUpdate();
			if (Input.GetKeyDown((KeyCode)286))
			{
				_ = Customer.UnlockedCustomers.ToList<Customer>()[0];
			}
		}

		public override void OnLateUpdate()
		{
			((MelonBase)this).OnLateUpdate();
			ModMixingStations modMixingStations = Get<ModMixingStations>();
			if (modMixingStations?.Configuration != null)
			{
				MixingStationMk2Registry.RefreshAllMixing(modMixingStations.Configuration);
			}
		}
	}
}
namespace Lithium.Util
{
	public static class DeliveryUtils
	{
		public static readonly Dictionary<string, float> DeliveryFeeOverrides = new Dictionary<string, float>();

		private static void SetDeliveryShopOpen(DeliveryShop shop, bool open)
		{
			Traverse.Create((object)shop).Property("IsOpen", (object[])null).SetValue((object)open);
		}

		private static bool GetDeliveryShopOpen(DeliveryShop shop)
		{
			return Traverse.Create((object)shop).Property("IsOpen", (object[])null).GetValue<bool>();
		}

		public static void ApplyDeliveryOverrides()
		{
			DeliveryFeeOverrides.Clear();
			Dictionary<string, DeliveryShop> dictionary = (from s in ((IEnumerable<DeliveryShop>)Object.FindObjectsOfType<DeliveryShop>(true)).ToList()
				where (Object)(object)s != (Object)null && (Object)(object)s.MatchingShop != (Object)null
				select s).ToDictionary((DeliveryShop s) => s.MatchingShop.ShopName, (DeliveryShop s) => s);
			foreach (KeyValuePair<string, DeliverySettings> delivery in Core.Get<ModShops>().Configuration.Deliveries)
			{
				if (!dictionary.TryGetValue(delivery.Key, out var value))
				{
					continue;
				}
				switch (delivery.Value.Availability)
				{
				case DeliveryAvailabilitySettings.Unchanged:
				{
					switch (value.MatchingShop.ShopName)
					{
					case "Albert Hoover":
					{
						Albert val2 = Object.FindObjectOfType<Albert>();
						SetDeliveryShopOpen(value, ((NPC)val2).RelationData.RelationDelta > Supplier.DELIVERY_RELATIONSHIP_REQUIREMENT);
						continue;
					}
					case "Shirley Watts":
					{
						Shirley val = Object.FindObjectOfType<Shirley>();
						SetDeliveryShopOpen(value, ((NPC)val).RelationData.RelationDelta > Supplier.DELIVERY_RELATIONSHIP_REQUIREMENT);
						continue;
					}
					case "Salvador Moreno":
					{
						Salvador val3 = Object.FindObjectOfType<Salvador>();
						SetDeliveryShopOpen(value, ((NPC)val3).RelationData.RelationDelta > Supplier.DELIVERY_RELATIONSHIP_REQUIREMENT);
						continue;
					}
					}
					string shopName = value.MatchingShop.ShopName;
					if (string.IsNullOrEmpty(shopName) || shopName.IndexOf("Fungal", StringComparison.OrdinalIgnoreCase) < 0)
					{
						continue;
					}
					foreach (Supplier item in Object.FindObjectsOfType<Supplier>(true))
					{
						if (!((Object)(object)item == (Object)null))
						{
							string name = ((object)item).GetType().Name;
							if (name != null && name.IndexOf("Fungal", StringComparison.OrdinalIgnoreCase) >= 0)
							{
								SetDeliveryShopOpen(value, ((NPC)item).RelationData.RelationDelta > Supplier.DELIVERY_RELATIONSHIP_REQUIREMENT);
								break;
							}
						}
					}
					continue;
				}
				case DeliveryAvailabilitySettings.Never:
					SetDeliveryShopOpen(value, open: false);
					break;
				case DeliveryAvailabilitySettings.Always:
					SetDeliveryShopOpen(value, open: true);
					break;
				case DeliveryAvailabilitySettings.AfterReachingXP:
					SetDeliveryShopOpen(value, NetworkSingleton<LevelManager>.Instance.TotalXP >= delivery.Value.XPRequirement);
					break;
				default:
					throw new ArgumentOutOfRangeException();
				}
				DeliveryFeeOverrides[delivery.Key] = delivery.Value.DeliveryFee;
				if ((Object)(object)value.DeliveryFeeLabel != (Object)null)
				{
					value.DeliveryFeeLabel.text = $"${delivery.Value.DeliveryFee:0}";
				}
				((Component)value).gameObject.SetActive(GetDeliveryShopOpen(value));
			}
		}
	}
	public static class SuccessChanceCalculator
	{
		public static float CalculateSuccess(EDrugType drugType, EQuality quality, float qualityLevelModifier, ECustomerStandard standard, string[] desires, string[] effects, CustomerAffinityData affinities, bool includeDrugPreference, float baseAcceptance)
		{
			//IL_00dd: Unknown result type (might be due to invalid IL or missing references)
			//IL_00de: Unknown result type (might be due to invalid IL or missing references)
			//IL_00df: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Expected I4, but got Unknown
			//IL_018b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0190: Unknown result type (might be due to invalid IL or missing references)
			float num2;
			if (desires.Length != 0)
			{
				int num = 0;
				foreach (string item in desires.Where((string d) => !string.IsNullOrEmpty(d)))
				{
					num += (effects.Contains(item) ? 1 : 0);
				}
				num2 = (float)num / (float)desires.Length;
				Core.Logger.Msg($"Sample offering: Covered {num} desires. Base acceptance {num2 * 100f:F1}%");
			}
			else
			{
				Core.Logger.Msg("Sample offering: No desired. Base acceptance 100%");
				num2 = 1f;
			}
			int num3 = quality - standard;
			Core.Logger.Msg($"Sample offering: Quality difference {num3} levels");
			num2 += qualityLevelModifier * (float)num3;
			Core.Logger.Msg($"Adjusted acceptance: {num2 * 100f:F1}%");
			if (includeDrugPreference)
			{
				Enumerator<ProductTypeAffinity> enumerator2 = affinities.ProductAffinities.GetEnumerator();
				while (enumerator2.MoveNext())
				{
					ProductTypeAffinity current2 = enumerator2.Current;
					if (current2.DrugType == drugType)
					{
						Core.Logger.Msg($"Sample offering: Product affinity modifier: {current2.Affinity * 100f:F1}%");
						num2 *= current2.Affinity;
						break;
					}
				}
			}
			num2 += baseAcceptance;
			Core.Logger.Msg($"Sample offering: Final acceptance is {Mathf.Clamp01(num2):F1}%");
			return Mathf.Clamp01(num2);
		}
	}
	public class WeightedNormalizer
	{
		private readonly List<float> _weights = new List<float>();

		private readonly List<float> _values = new List<float>();

		private readonly List<float> _cdf = new List<float>();

		private bool _isInitialized;

		public void Add(float weight, float value)
		{
			if (weight < 0f)
			{
				throw new ArgumentOutOfRangeException("weight", "Weight must be non-negative.");
			}
			_weights.Add(weight);
			_values.Add(value);
			_isInitialized = false;
		}

		private void Initialize()
		{
			_cdf.Clear();
			float num = _weights.Sum();
			if (num == 0f)
			{
				_cdf.Clear();
				_cdf.Add(1f);
				_isInitialized = true;
				return;
			}
			float num2 = 0f;
			foreach (float weight in _weights)
			{
				num2 += weight / num;
				_cdf.Add(num2);
			}
			_isInitialized = true;
		}

		public float Evaluate(float n)
		{
			if (!_isInitialized)
			{
				Initialize();
			}
			if (_values.Count == 0)
			{
				throw new InvalidOperationException("No values added to normalize.");
			}
			if (!(n <= 0f))
			{
				if (n >= 1f)
				{
					List<float> values = _values;
					return values[values.Count - 1];
				}
				int num = _cdf.FindIndex((float x) => x > n);
				switch (num)
				{
				case -1:
				{
					List<float> values2 = _values;
					return values2[values2.Count - 1];
				}
				case 0:
					return _values[0];
				default:
				{
					int index = num - 1;
					float num2 = _cdf[index];
					float num3 = _cdf[num];
					float num4 = (n - num2) / (num3 - num2);
					float num5 = _values[index];
					float num6 = _values[num];
					return num5 + (num6 - num5) * num4;
				}
				}
			}
			return _values[0];
		}
	}
	public class PickerEmptyException : Exception
	{
	}
	public class WeightedPicker<T>
	{
		private readonly Random _random;

		private bool _hasChanged;

		private readonly Dictionary<T, float> _dictionary = new Dictionary<T, float>();

		private double _totalWeight;

		public int Count => _dictionary.Count;

		public float this[T key]
		{
			get
			{
				return _dictionary[key];
			}
			set
			{
				_dictionary[key] = value;
				_hasChanged = true;
			}
		}

		public WeightedPicker(Random random)
		{
			_random = random;
		}

		public WeightedPicker()
			: this(new Random(Guid.NewGuid().GetHashCode()))
		{
		}

		public T Pick()
		{
			if (_hasChanged)
			{
				Rebuild();
			}
			float value = (float)_random.Next((int)(_totalWeight * 100.0)) / 100f;
			return PickManually(value);
		}

		public T PickManually(float value)
		{
			if (_hasChanged)
			{
				Rebuild();
			}
			value = Math.Min((float)_totalWeight, Math.Max(0f, value));
			float num = 0f;
			KeyValuePair<T, float>? keyValuePair = null;
			foreach (KeyValuePair<T, float> item in _dictionary)
			{
				if (num > value)
				{
					break;
				}
				keyValuePair = item;
				num += item.Value;
			}
			if (!keyValuePair.HasValue)
			{
				throw new PickerEmptyException();
			}
			return keyValuePair.Value.Key;
		}

		private void Rebuild()
		{
			_totalWeight = _dictionary.Values.Sum();
			_hasChanged = false;
		}

		public void Add(T value, float weight)
		{
			_dictionary.Add(value, weight);
			_hasChanged = true;
		}

		public void AddRange(IEnumerable<KeyValuePair<T, float>> entries)
		{
			foreach (KeyValuePair<T, float> entry in entries)
			{
				_dictionary.Add(entry.Key, entry.Value);
			}
			_hasChanged = true;
		}

		public bool Remove(T key)
		{
			_hasChanged = true;
			return _dictionary.Remove(key);
		}

		public void Clear()
		{
			_dictionary.Clear();
			_hasChanged = true;
		}
	}
}
namespace Lithium.Modules
{
	public abstract class ModuleBase
	{
		public abstract void Load();

		public abstract void Apply();
	}
	public abstract class ModuleBase<TConfiguration> : ModuleBase where TConfiguration : ModuleConfiguration
	{
		public TConfiguration Configuration { get; private set; }

		protected virtual void OnBeforeConfigurationLoaded()
		{
		}

		public override void Load()
		{
			Configuration = Activator.CreateInstance<TConfiguration>();
			OnBeforeConfigurationLoaded();
			Configuration.LoadConfiguration();
		}
	}
	public abstract class ModuleConfiguration
	{
		private static readonly string ConfigFolder = Path.Combine(MelonEnvironment.UserDataDirectory, "Lithium");

		[JsonProperty(Order = -500)]
		public bool Enabled;

		[JsonIgnore]
		public abstract string Name { get; }

		public string GetConfigFile()
		{
			return Path.Combine(ConfigFolder, Name + ".json");
		}

		public void SaveConfiguration()
		{
			if (!Directory.Exists(ConfigFolder))
			{
				Directory.CreateDirectory(ConfigFolder);
			}
			string configFile = GetConfigFile();
			string contents = JsonConvert.SerializeObject((object)this, (Formatting)1);
			File.WriteAllText(configFile, contents);
		}

		public void LoadConfiguration()
		{
			//IL_0015: 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_0022: Expected O, but got Unknown
			string configFile = GetConfigFile();
			if (File.Exists(configFile))
			{
				string text = File.ReadAllText(configFile);
				JsonSerializerSettings val = new JsonSerializerSettings
				{
					DefaultValueHandling = (DefaultValueHandling)2
				};
				JsonConvert.PopulateObject(text, (object)this, val);
			}
			else
			{
				SaveConfiguration();
			}
		}
	}
}
namespace Lithium.Modules.MixingStations
{
	public class ModMixingStationsConfiguration : ModuleConfiguration
	{
		public override string Name => "MixingStation";

		public int InputCapacity { get; set; } = 20;


		public float MixSpeed { get; set; } = 1f;


		[JsonProperty(/*Could not decode attribute arguments.*/)]
		public int? MixStepsPerSecond { get; set; }

		internal float GetEffectiveMixSpeed()
		{
			if (MixStepsPerSecond.HasValue && Mathf.Approximately(MixSpeed, 1f))
			{
				return Mathf.Max(0.01f, (float)MixStepsPerSecond.Value);
			}
			return Mathf.Max(0.01f, MixSpeed);
		}
	}
	public class ModMixingStations : ModuleBase<ModMixingStationsConfiguration>
	{
		public override void Apply()
		{
			_ = base.Configuration.Enabled;
		}
	}
}
namespace Lithium.Modules.MixingStations.Patches
{
	internal static class MixingStationClockReflection
	{
		internal static object ResolveClock(MixingStation station)
		{
			if ((Object)(object)station.Clock != (Object)null)
			{
				return station.Clock;
			}
			if (!(station is MixingStationMk2))
			{
				return null;
			}
			string[] array = new string[8] { "Clock", "clock", "Alarm", "alarm", "MixingStationCanvas", "mixingStationCanvas", "Canvas", "canvas" };
			foreach (string text in array)
			{
				try
				{
					object obj = ResolveTraversedToAlarm(Traverse.Create((object)station).Field(text).GetValue());
					if (obj != null)
					{
						return obj;
					}
				}
				catch
				{
				}
				try
				{
					object obj3 = ResolveTraversedToAlarm(Traverse.Create((object)station).Property(text, (object[])null).GetValue());
					if (obj3 != null)
					{
						return obj3;
					}
				}
				catch
				{
				}
			}
			return FindDigitalAlarmUnderTransform(((Component)station).transform);
		}

		private static object ResolveTraversedToAlarm(object v)
		{
			if (v == null)
			{
				return null;
			}
			if (LooksLikeDigitalAlarm(v))
			{
				return v;
			}
			GameObject val = (GameObject)((v is GameObject) ? v : null);
			if (val != null)
			{
				return FindDigitalAlarmUnderTransform(val.transform);
			}
			Component val2 = (Component)((v is Component) ? v : null);
			if (val2 != null)
			{
				return FindDigitalAlarmUnderTransform(val2.transform);
			}
			return null;
		}

		private static bool LooksLikeDigitalAlarm(object o)
		{
			string name = o.GetType().Name;
			if (name != null)
			{
				return name.IndexOf("DigitalAlarm", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		private static object FindDigitalAlarmUnderTransform(Transform t)
		{
			if ((Object)(object)t == (Object)null)
			{
				return null;
			}
			foreach (MonoBehaviour componentsInChild in ((Component)t).GetComponentsInChildren<MonoBehaviour>(true))
			{
				if ((Object)(object)componentsInChild != (Object)null && LooksLikeDigitalAlarm(componentsInChild))
				{
					return componentsInChild;
				}
			}
			return null;
		}

		internal static void SetScreenLit(object clock, bool lit)
		{
			clock?.GetType().GetMethod("SetScreenLit", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(clock, new object[1] { lit });
		}

		internal static void DisplayMinutes(object clock, int minutes)
		{
			clock?.GetType().GetMethod("DisplayMinutes", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(clock, new object[1] { minutes });
		}

		internal static void DisplayText(object clock, string text)
		{
			clock?.GetType().GetMethod("DisplayText", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)?.Invoke(clock, new object[1] { text });
		}
	}
	[HarmonyPatch(typeof(MixingStation), "Start")]
	public class MixingStationCapacityPatch
	{
		[HarmonyPostfix]
		public static void MixingStationCapacity(MixingStation __instance)
		{
			MixingStationPatchLogic.StartPostfix(__instance);
			MixingStationMk2 val = __instance.AsMk2();
			if ((Object)(object)val != (Object)null)
			{
				MixingStationMk2Registry.Register(val);
			}
		}
	}
	[HarmonyPatch(typeof(MixingStation), "GetMixTimeForCurrentOperation")]
	internal static class MixingStationGetMixTimePatch
	{
		[HarmonyPostfix]
		public static void Postfix(ref int __result)
		{
			if (!MixingStationPatchLogic.SuppressGetMixTimePostfix)
			{
				MixingStationPatchLogic.GetMixTimePostfix(ref __result);
			}
		}
	}
	internal static class MixingStationMk2UiBroadcast
	{
		private sealed class CachedRefs
		{
			internal object Clock;

			internal List<TMP_Text> TimerTmps;

			internal int LastWritten = int.MinValue;

			internal bool LastWasIdle;
		}

		private static readonly Dictionary<int, CachedRefs> CacheByStationId = new Dictionary<int, CachedRefs>();

		private static readonly Regex RxMinsRemaining = new Regex("\\d+(\\.\\d+)?\\s*mins?\\s*remaining", RegexOptions.IgnoreCase | RegexOptions.Compiled);

		private static readonly Regex RxMinutesRestantes = new Regex("\\d+(\\.\\d+)?\\s*minutes?\\s*restantes?", RegexOptions.IgnoreCase | RegexOptions.Compiled);

		private static readonly Regex RxLeadingNumber = new Regex("^\\s*\\d+(\\.\\d+)?", RegexOptions.Compiled);

		internal static void ClearStationCaches(int stationId)
		{
			CacheByStationId.Remove(stationId);
		}

		internal static void WriteRemainingMinutesToMk2Ui(MixingStationMk2 mk2, int remainingMinutes)
		{
			if ((Object)(object)mk2 == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)mk2).GetInstanceID();
			CachedRefs orBuildCache = GetOrBuildCache(mk2, instanceID);
			if (orBuildCache == null || (!orBuildCache.LastWasIdle && orBuildCache.LastWritten == remainingMinutes))
			{
				return;
			}
			orBuildCache.LastWritten = remainingMinutes;
			orBuildCache.LastWasIdle = false;
			if (orBuildCache.Clock != null)
			{
				MixingStationClockReflection.SetScreenLit(orBuildCache.Clock, lit: true);
				MixingStationClockReflection.DisplayMinutes(orBuildCache.Clock, remainingMinutes);
			}
			if (orBuildCache.TimerTmps == null)
			{
				return;
			}
			for (int i = 0; i < orBuildCache.TimerTmps.Count; i++)
			{
				TMP_Text val = orBuildCache.TimerTmps[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				string text = val.text;
				if (!string.IsNullOrEmpty(text))
				{
					string text2 = RxMinsRemaining.Replace(text, $"{remainingMinutes} mins remaining");
					if (text2 == text)
					{
						text2 = RxMinutesRestantes.Replace(text, $"{remainingMinutes} minutes restantes");
					}
					if (text2 == text)
					{
						text2 = RxLeadingNumber.Replace(text, remainingMinutes.ToString());
					}
					if (text2 != text)
					{
						val.text = text2;
					}
				}
			}
		}

		internal static void BlankMk2Ui(MixingStationMk2 mk2)
		{
			if ((Object)(object)mk2 == (Object)null)
			{
				return;
			}
			int instanceID = ((Object)mk2).GetInstanceID();
			if (CacheByStationId.TryGetValue(instanceID, out var value) && !value.LastWasIdle)
			{
				value.LastWasIdle = true;
				value.LastWritten = int.MinValue;
				if (value.Clock != null)
				{
					MixingStationClockReflection.SetScreenLit(value.Clock, lit: false);
					MixingStationClockReflection.DisplayText(value.Clock, string.Empty);
				}
			}
		}

		private static CachedRefs GetOrBuildCache(MixingStationMk2 mk2, int sid)
		{
			if (CacheByStationId.TryGetValue(sid, out var value) && value != null)
			{
				return value;
			}
			CachedRefs cachedRefs = new CachedRefs();
			try
			{
				cachedRefs.Clock = MixingStationClockReflection.ResolveClock((MixingStation)(object)mk2);
			}
			catch
			{
			}
			try
			{
				Transform transform = ((Component)mk2).transform;
				if ((Object)(object)transform != (Object)null)
				{
					cachedRefs.TimerTmps = new List<TMP_Text>(4);
					foreach (TMP_Text componentsInChild in ((Component)transform).GetComponentsInChildren<TMP_Text>(true))
					{
						if (!((Object)(object)componentsInChild == (Object)null))
						{
							string text = componentsInChild.text;
							if (!string.IsNullOrEmpty(text) && LooksLikeMinutesRemainingLabel(text))
							{
								cachedRefs.TimerTmps.Add(componentsInChild);
							}
						}
					}
				}
			}
			catch
			{
			}
			CacheByStationId[sid] = cachedRefs;
			return cachedRefs;
		}

		private static bool LooksLikeMinutesRemainingLabel(string s)
		{
			if (s.IndexOf("min", StringComparison.OrdinalIgnoreCase) < 0 && s.IndexOf("remaining", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return s.IndexOf("restant", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}
	}
	[HarmonyPatch]
	internal static class MixingStationMk2UpdateDisplayPatch
	{
		private static MethodBase TargetMethod()
		{
			MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(MixingStationMk2), "LateUpdate", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				return methodInfo;
			}
			methodInfo = AccessTools.DeclaredMethod(typeof(MixingStation), "LateUpdate", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				return methodInfo;
			}
			methodInfo = AccessTools.DeclaredMethod(typeof(MixingStationMk2), "Update", (Type[])null, (Type[])null);
			if (methodInfo != null)
			{
				return methodInfo;
			}
			return AccessTools.DeclaredMethod(typeof(MixingStation), "Update", (Type[])null, (Type[])null);
		}

		private static bool Prepare()
		{
			return TargetMethod() != null;
		}

		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(MixingStation __instance)
		{
			MixingStationMk2 val = __instance.AsMk2();
			if ((Object)(object)val == (Object)null)
			{
				return;
			}
			ModMixingStations modMixingStations = Core.Get<ModMixingStations>();
			if (modMixingStations?.Configuration == null || !modMixingStations.Configuration.Enabled)
			{
				return;
			}
			try
			{
				if (((MixingStation)val).CurrentMixOperation == null)
				{
					MixingStationMk2UiBroadcast.BlankMk2Ui(val);
					return;
				}
				int scaledRequiredMinutes = MixingStationPatchLogic.GetScaledRequiredMinutes((MixingStation)(object)val, modMixingStations.Configuration);
				int remainingMinutes = Mathf.Max(0, scaledRequiredMinutes - ((MixingStation)val).CurrentMixTime);
				MixingStationMk2UiBroadcast.WriteRemainingMinutesToMk2Ui(val, remainingMinutes);
			}
			catch
			{
			}
		}
	}
	internal static class MixingStationMk2Registry
	{
		private static readonly List<MixingStationMk2> Stations = new List<MixingStationMk2>();

		internal static void Register(MixingStationMk2 mk2)
		{
			if (!((Object)(object)mk2 == (Object)null) && !Stations.Contains(mk2))
			{
				Stations.Add(mk2);
			}
		}

		internal static void Unregister(MixingStationMk2 mk2)
		{
			if ((Object)(object)mk2 != (Object)null)
			{
				Stations.Remove(mk2);
			}
			if ((Object)(object)mk2 != (Object)null)
			{
				MixingStationMk2UiBroadcast.ClearStationCaches(((Object)mk2).GetInstanceID());
			}
		}

		internal static void RefreshAllMixing(ModMixingStationsConfiguration config)
		{
			if (config == null || !config.Enabled)
			{
				return;
			}
			for (int num = Stations.Count - 1; num >= 0; num--)
			{
				MixingStationMk2 val = Stations[num];
				if ((Object)(object)val == (Object)null)
				{
					Stations.RemoveAt(num);
				}
				else
				{
					try
					{
						if (((MixingStation)val).CurrentMixOperation == null)
						{
							MixingStationMk2UiBroadcast.BlankMk2Ui(val);
						}
						else
						{
							int scaledRequiredMinutes = MixingStationPatchLogic.GetScaledRequiredMinutes((MixingStation)(object)val, config);
							int remainingMinutes = Mathf.Max(0, scaledRequiredMinutes - ((MixingStation)val).CurrentMixTime);
							MixingStationMk2UiBroadcast.WriteRemainingMinutesToMk2Ui(val, remainingMinutes);
						}
					}
					catch
					{
					}
				}
			}
		}
	}
	[HarmonyPatch(typeof(MixingStation), "OnDestroy")]
	internal static class MixingStationMk2LifecyclePatch
	{
		private static bool Prepare()
		{
			return AccessTools.DeclaredMethod(typeof(MixingStation), "OnDestroy", (Type[])null, (Type[])null) != null;
		}

		[HarmonyPostfix]
		private static void Postfix(MixingStation __instance)
		{
			MixingStationMk2 val = __instance.AsMk2();
			if ((Object)(object)val != (Object)null)
			{
				MixingStationMk2Registry.Unregister(val);
			}
		}
	}
	internal static class MixingStationPatchLogic
	{
		[ThreadStatic]
		internal static bool SuppressGetMixTimePostfix;

		private static readonly Dictionary<int, int> LastMixProgressDailyMinSum = new Dictionary<int, int>();

		internal static TimeManager ResolveTimeManager()
		{
			try
			{
				TimeManager instance = NetworkSingleton<TimeManager>.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					return instance;
				}
			}
			catch
			{
			}
			try
			{
				TimeManager instance2 = NetworkSingleton<TimeManager>.Instance;
				if ((Object)(object)instance2 != (Object)null)
				{
					return instance2;
				}
			}
			catch
			{
			}
			return null;
		}

		internal static int GetDailyMinSumSafe()
		{
			int num = -1;
			try
			{
				TimeManager instance = NetworkSingleton<TimeManager>.Instance;
				if ((Object)(object)instance != (Object)null)
				{
					num = Mathf.Max(num, instance.DailyMinSum);
				}
			}
			catch
			{
			}
			try
			{
				TimeManager instance2 = NetworkSingleton<TimeManager>.Instance;
				if ((Object)(object)instance2 != (Object)null)
				{
					num = Mathf.Max(num, instance2.DailyMinSum);
				}
			}
			catch
			{
			}
			if (num < 0)
			{
				return 0;
			}
			return num;
		}

		internal static bool CanAdvanceMixTimeAsAuthority()
		{
			try
			{
				if (InstanceFinder.IsServer)
				{
					return true;
				}
			}
			catch
			{
			}
			try
			{
				if (InstanceFinder.IsClient && !InstanceFinder.IsServer)
				{
					return false;
				}
			}
			catch
			{
			}
			return true;
		}

		internal static bool OnMinPassPrefix(MixingStation __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return false;
			}
			ModMixingStationsConfiguration configuration = Core.Get<ModMixingStations>().Configuration;
			if (configuration == null)
			{
				return false;
			}
			bool flag = false;
			try
			{
				flag = __instance.CurrentMixOperation != null;
			}
			catch
			{
			}
			int num = 0;
			try
			{
				num = ((__instance.OutputSlot != null) ? __instance.OutputSlot.Quantity : 0);
			}
			catch
			{
			}
			if (flag || num > 0)
			{
				int num2 = 0;
				int num3 = 0;
				try
				{
					num3 = __instance.CurrentMixTime;
				}
				catch
				{
				}
				if (flag)
				{
					num2 = SafeGetScaledRequired(__instance, configuration);
					int num4 = num3;
					if (CanAdvanceMixTimeAsAuthority())
					{
						int instanceID = ((Object)__instance).GetInstanceID();
						int dailyMinSumSafe = GetDailyMinSumSafe();
						if (num4 <= 0)
						{
							LastMixProgressDailyMinSum.Remove(instanceID);
						}
						if (!LastMixProgressDailyMinSum.TryGetValue(instanceID, out var value) || value != dailyMinSumSafe)
						{
							LastMixProgressDailyMinSum[instanceID] = dailyMinSumSafe;
							int num5 = Mathf.Min(num4 + 1, num2);
							try
							{
								__instance.CurrentMixTime = num5;
							}
							catch
							{
							}
							num3 = num5;
							if (num4 < num2 && num5 >= num2)
							{
								TryIncrementMixingCompletedVariable();
								try
								{
									__instance.MixingDone_Networked();
								}
								catch
								{
								}
							}
						}
					}
				}
				int num6 = Mathf.Max(0, num2 - num3);
				MixingStationMk2 val = __instance.AsMk2();
				if ((Object)(object)val != (Object)null)
				{
					MixingStationMk2UiBroadcast.WriteRemainingMinutesToMk2Ui(val, num6);
				}
				else
				{
					object obj6 = MixingStationClockReflection.ResolveClock(__instance);
					if (obj6 != null)
					{
						MixingStationClockReflection.SetScreenLit(obj6, lit: true);
						MixingStationClockReflection.DisplayMinutes(obj6, num6);
					}
				}
				try
				{
					if ((Object)(object)__instance.Light != (Object)null)
					{
						if (__instance.IsMixingDone)
						{
							__instance.Light.isOn = GetDailyMinSumSafe() % 2 == 0;
						}
						else
						{
							__instance.Light.isOn = true;
						}
					}
				}
				catch
				{
				}
			}
			else
			{
				MixingStationMk2 val2 = __instance.AsMk2();
				if ((Object)(object)val2 != (Object)null)
				{
					MixingStationMk2UiBroadcast.BlankMk2Ui(val2);
				}
				else
				{
					object obj8 = MixingStationClockReflection.ResolveClock(__instance);
					if (obj8 != null)
					{
						MixingStationClockReflection.SetScreenLit(obj8, lit: false);
						MixingStationClockReflection.DisplayText(obj8, string.Empty);
					}
				}
				try
				{
					if ((Object)(object)__instance.Light != (Object)null && __instance.IsMixingDone)
					{
						__instance.Light.isOn = false;
					}
				}
				catch
				{
				}
			}
			return false;
		}

		private static int SafeGetScaledRequired(MixingStation station, ModMixingStationsConfiguration config)
		{
			SuppressGetMixTimePostfix = true;
			try
			{
				int num = 0;
				try
				{
					num = station.GetMixTimeForCurrentOperation();
				}
				catch
				{
					return 1;
				}
				if (!config.Enabled)
				{
					return Mathf.Max(1, num);
				}
				float num2 = config.GetEffectiveMixSpeed();
				if (num2 <= 0f)
				{
					num2 = 1f;
				}
				return Mathf.Max(1, Mathf.FloorToInt((float)num / num2));
			}
			finally
			{
				SuppressGetMixTimePostfix = false;
			}
		}

		private static void TryIncrementMixingCompletedVariable()
		{
			try
			{
				VariableDatabase instance = NetworkSingleton<VariableDatabase>.Instance;
				if (!((Object)(object)instance == (Object)null))
				{
					float value = instance.GetValue<float>("Mixing_Operations_Completed");
					instance.SetVariableValue("Mixing_Operations_Completed", (value + 1f).ToString(), true);
				}
			}
			catch
			{
			}
		}

		internal static int GetScaledRequiredMinutes(MixingStation station, ModMixingStationsConfiguration config)
		{
			SuppressGetMixTimePostfix = true;
			try
			{
				int mixTimeForCurrentOperation = station.GetMixTimeForCurrentOperation();
				if (!config.Enabled)
				{
					return mixTimeForCurrentOperation;
				}
				float effectiveMixSpeed = config.GetEffectiveMixSpeed();
				return Mathf.Max(1, Mathf.FloorToInt((float)mixTimeForCurrentOperation / effectiveMixSpeed));
			}
			finally
			{
				SuppressGetMixTimePostfix = false;
			}
		}

		internal static void GetMixTimePostfix(ref int __result)
		{
			ModMixingStationsConfiguration configuration = Core.Get<ModMixingStations>().Configuration;
			if (configuration.Enabled)
			{
				float effectiveMixSpeed = configuration.GetEffectiveMixSpeed();
				__result = Mathf.Max(1, Mathf.FloorToInt((float)__result / effectiveMixSpeed));
			}
		}

		internal static void StartPostfix(MixingStation __instance)
		{
			ModMixingStationsConfiguration configuration = Core.Get<ModMixingStations>().Configuration;
			if (configuration.Enabled)
			{
				__instance.MaxMixQuantity = configuration.InputCapacity;
			}
		}
	}
	[HarmonyPatch(typeof(MixingStation), "OnMinPass")]
	internal static class MixingStationOnMinPassPatch
	{
		[HarmonyPrefix]
		public static bool Prefix(MixingStation __instance)
		{
			return MixingStationPatchLogic.OnMinPassPrefix(__instance);
		}
	}
	[HarmonyPatch]
	internal static class MixingStationMk2OnMinPassPatch
	{
		private static bool Prepare()
		{
			MethodInfo methodInfo = AccessTools.Method(typeof(MixingStationMk2), "OnMinPass", (Type[])null, (Type[])null);
			MethodInfo methodInfo2 = AccessTools.Method(typeof(MixingStation), "OnMinPass", (Type[])null, (Type[])null);
			if (methodInfo != null && methodInfo2 != null)
			{
				return (object)methodInfo != methodInfo2;
			}
			return false;
		}

		private static MethodBase TargetMethod()
		{
			return AccessTools.Method(typeof(MixingStationMk2), "OnMinPass", (Type[])null, (Type[])null);
		}

		[HarmonyPrefix]
		public static bool Prefix(MixingStationMk2 __instance)
		{
			return MixingStationPatchLogic.OnMinPassPrefix((MixingStation)(object)__instance);
		}
	}
	[HarmonyPatch]
	internal static class MixingStationCanvasUpdatePatch
	{
		private sealed class CanvasCache
		{
			internal MixingStation Station;

			internal List<TMP_Text> Tmps;

			internal int LastWritten = int.MinValue;

			internal bool LastWasIdle;
		}

		private static readonly Dictionary<int, CanvasCache> CacheByCanvasId = new Dictionary<int, CanvasCache>();

		private static readonly Regex RxMinsRemaining = new Regex("\\d+(\\.\\d+)?\\s*mins?\\s*remaining", RegexOptions.IgnoreCase | RegexOptions.Compiled);

		private static readonly Regex RxLeadingMins = new Regex("^\\s*\\d+(\\.\\d+)?\\s*mins?", RegexOptions.IgnoreCase | RegexOptions.Compiled);

		private static MethodBase TargetMethod()
		{
			return AccessTools.DeclaredMethod(typeof(MixingStationCanvas), "LateUpdate", (Type[])null, (Type[])null) ?? AccessTools.DeclaredMethod(typeof(MixingStationCanvas), "Update", (Type[])null, (Type[])null);
		}

		private static bool Prepare()
		{
			return TargetMethod() != null;
		}

		[HarmonyPostfix]
		[HarmonyPriority(0)]
		private static void Postfix(MixingStationCanvas __instance)
		{
			if ((Object)(object)__instance == (Object)null)
			{
				return;
			}
			ModMixingStations modMixingStations = Core.Get<ModMixingStations>();
			if (modMixingStations?.Configuration == null || !modMixingStations.Configuration.Enabled)
			{
				return;
			}
			int instanceID = ((Object)__instance).GetInstanceID();
			if (!CacheByCanvasId.TryGetValue(instanceID, out var value) || value == null)
			{
				value = BuildCache(__instance);
				CacheByCanvasId[instanceID] = value;
			}
			MixingStation station = value.Station;
			if ((Object)(object)station == (Object)null)
			{
				return;
			}
			bool flag;
			try
			{
				flag = station.CurrentMixOperation != null;
			}
			catch
			{
				return;
			}
			if (!flag)
			{
				value.LastWasIdle = true;
				value.LastWritten = int.MinValue;
				return;
			}
			int scaledRequiredMinutes;
			try
			{
				scaledRequiredMinutes = MixingStationPatchLogic.GetScaledRequiredMinutes(station, modMixingStations.Configuration);
			}
			catch
			{
				return;
			}
			int num;
			try
			{
				num = Mathf.Max(0, scaledRequiredMinutes - station.CurrentMixTime);
			}
			catch
			{
				return;
			}
			if (!value.LastWasIdle && value.LastWritten == num)
			{
				return;
			}
			value.LastWasIdle = false;
			value.LastWritten = num;
			if (value.Tmps == null)
			{
				return;
			}
			for (int i = 0; i < value.Tmps.Count; i++)
			{
				TMP_Text val = value.Tmps[i];
				if ((Object)(object)val == (Object)null)
				{
					continue;
				}
				string text = val.text;
				if (!string.IsNullOrEmpty(text))
				{
					string text2 = RxMinsRemaining.Replace(text, $"{num} mins remaining");
					if (text2 == text)
					{
						text2 = RxLeadingMins.Replace(text, $"{num} mins");
					}
					if (text2 != text)
					{
						val.text = text2;
					}
				}
			}
		}

		private static CanvasCache BuildCache(MixingStationCanvas canvas)
		{
			CanvasCache canvasCache = new CanvasCache
			{
				Station = ResolveStation(canvas),
				Tmps = new List<TMP_Text>(4)
			};
			try
			{
				if ((Object)(object)((Component)canvas).transform != (Object)null)
				{
					foreach (TMP_Text componentsInChild in ((Component)canvas).GetComponentsInChildren<TMP_Text>(true))
					{
						if (!((Object)(object)componentsInChild == (Object)null))
						{
							string text = componentsInChild.text;
							if (!string.IsNullOrEmpty(text) && (text.IndexOf("min", StringComparison.OrdinalIgnoreCase) >= 0 || text.IndexOf("remaining", StringComparison.OrdinalIgnoreCase) >= 0))
							{
								canvasCache.Tmps.Add(componentsInChild);
							}
						}
					}
				}
			}
			catch
			{
			}
			return canvasCache;
		}

		private static MixingStation ResolveStation(MixingStationCanvas canvas)
		{
			Type typeFromHandle = typeof(MixingStationCanvas);
			string[] array = new string[5] { "MixingStation", "mixingStation", "Station", "station", "ParentStation" };
			foreach (string name in array)
			{
				try
				{
					PropertyInfo property = typeFromHandle.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (property != null)
					{
						object? value = property.GetValue(canvas);
						MixingStation val = (MixingStation)((value is MixingStation) ? value : null);
						if (val != null)
						{
							return val;
						}
					}
				}
				catch
				{
				}
				try
				{
					FieldInfo field = typeFromHandle.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (field != null)
					{
						object? value2 = field.GetValue(canvas);
						MixingStation val2 = (MixingStation)((value2 is MixingStation) ? value2 : null);
						if (val2 != null)
						{
							return val2;
						}
					}
				}
				catch
				{
				}
			}
			try
			{
				return ((Component)canvas).GetComponentInParent<MixingStation>();
			}
			catch
			{
				return null;
			}
		}
	}
	internal static class MixingStationMk2Check
	{
		internal static MixingStationMk2 AsMk2(this MixingStation station)
		{
			if ((Object)(object)station == (Object)null)
			{
				return null;
			}
			try
			{
				return ((Il2CppObjectBase)station).TryCast<MixingStationMk2>();
			}
			catch
			{
				return null;
			}
		}

		internal static bool IsMk2(this MixingStation station)
		{
			return (Object)(object)station.AsMk2() != (Object)null;
		}

		internal static Transform ResolveStationRoot(MixingStation station)
		{
			if ((Object)(object)station == (Object)null)
			{
				return null;
			}
			try
			{
				MixingStationMk2 val = station.AsMk2();
				if ((Object)(object)val != (Object)null && (Object)(object)((Component)val).transform != (Object)null)
				{
					return ((Component)val).transform;
				}
			}
			catch
			{
			}
			try
			{
				return ((Component)station).transform;
			}
			catch
			{
				return null;
			}
		}
	}
}
namespace Lithium.Modules.TrashGrabber
{
	public class ModTrashGrabberConfiguration : ModuleConfiguration
	{
		public override string Name => "TrashGrabber";

		public int CustomCapacity { get; set; } = 20;

	}
	public class ModTrashGrabber : ModuleBase<ModTrashGrabberConfiguration>
	{
		public override void Apply()
		{
			_ = base.Configuration.Enabled;
		}
	}
}
namespace Lithium.Modules.TrashGrabber.Patches
{
	[HarmonyPatch(typeof(Equippable_TrashGrabber), "GetCapacity")]
	public static class EquippableTrashGrabberGetCapacityPatch
	{
		[HarmonyPostfix]
		public static void Postfix(ref int __result, Equippable_TrashGrabber __instance)
		{
			ModTrashGrabberConfiguration configuration = Core.Get<ModTrashGrabber>().Configuration;
			if (configuration.Enabled)
			{
				__result = configuration.CustomCapacity - __instance.trashGrabberInstance.GetTotalSize();
			}
		}
	}
}
namespace Lithium.Modules.StackSizes
{
	public class ModStackSizesConfiguration : ModuleConfiguration
	{
		public override string Name => "StackSizes";

		public Dictionary<EItemCategory, int> CategorySizes { get; set; } = new Dictionary<EItemCategory, int>
		{
			{
				(EItemCategory)0,
				20
			},
			{
				(EItemCategory)1,
				20
			},
			{
				(EItemCategory)2,
				20
			},
			{
				(EItemCategory)3,
				10
			},
			{
				(EItemCategory)4,
				10
			},
			{
				(EItemCategory)5,
				10
			},
			{
				(EItemCategory)6,
				1000
			},
			{
				(EItemCategory)7,
				20
			},
			{
				(EItemCategory)8,
				20
			},
			{
				(EItemCategory)9,
				20
			},
			{
				(EItemCategory)10,
				10
			},
			{
				(EItemCategory)11,
				10
			},
			{
				(EItemCategory)12,
				10
			}
		};


		public Dictionary<string, int> ItemOverrides { get; set; } = new Dictionary<string, int>();


		public List<string> IgnoredItems { get; set; } = new List<string>();

	}
	public class ModStackSizes : ModuleBase<ModStackSizesConfiguration>
	{
		public override void Apply()
		{
			_ = base.Configuration.Enabled;
		}
	}
	public static class ItemRegistry
	{
		public static List<ItemDefinition> AllItemDefinitions = new List<ItemDefinition>();

		public static void UpdateEntireRegistry()
		{
			foreach (ItemDefinition allItemDefinition in AllItemDefinitions)
			{
				UpdateItemDefinition(allItemDefinition);
			}
		}

		public static void UpdateItemDefinition(ItemDefinition itemDefinition)
		{
			//IL_004c: Unknown result type (might be due to invalid IL or missing references)
			//IL_007b: Unknown result type (might be due to invalid IL or missing references)
			ModStackSizesConfiguration configuration = Core.Get<ModStackSizes>().Configuration;
			if (configuration.Enabled && !configuration.IgnoredItems.Contains(((BaseItemDefinition)itemDefinition).ID))
			{
				if (configuration.ItemOverrides.TryGetValue(((BaseItemDefinition)itemDefinition).ID, out var value))
				{
					((BaseItemDefinition)itemDefinition).StackLimit = value;
					return;
				}
				if (configuration.CategorySizes.TryGetValue(((BaseItemDefinition)itemDefinition).Category, out value))
				{
					((BaseItemDefinition)itemDefinition).StackLimit = value;
					return;
				}
				MelonLogger.Warning($"Found item for category {((BaseItemDefinition)itemDefinition).Category}, but no category value");
			}
		}
	}
}
namespace Lithium.Modules.StackSizes.Patches
{
	[HarmonyPatch(typeof(ItemUIManager), "UpdateCashDragAmount")]
	[HarmonyPatch(typeof(ItemUIManager), "StartDragCash")]
	[HarmonyPatch(typeof(ItemUIManager), "EndCashDrag")]
	public class CashDragPatch
	{
		[HarmonyTranspiler]
		public static IEnumerable<CodeInstruction> TranspilerPatch(IEnumerable<CodeInstruction> instructions)
		{
			foreach (CodeInstruction instruction in instructions)
			{
				if (instruction.opcode == OpCodes.Ldc_R4 && (float)instruction.operand == 1000f)
				{
					yield return new CodeInstruction(OpCodes.Ldc_R4, (object)5000f);
				}
				else
				{
					yield return instruction;
				}
			}
		}
	}
	[HarmonyPatch(typeof(Registry), "AddToRegistry")]
	public class RegistryAddToRegistryPatch
	{
		[HarmonyPostfix]
		public static void RegistryAddToRegistry(Registry __instance, ItemDefinition item)
		{
			CollectionExtensions.AddItem<ItemDefinition>((IEnumerable<ItemDefinition>)ItemRegistry.AllItemDefinitions, item);
			ItemRegistry.UpdateItemDefinition(item);
		}
	}
	[HarmonyPatch(typeof(Registry), "Start")]
	public class RegistryStartPatch
	{
		[HarmonyPostfix]
		public static void RegistryStart(Registry __instance)
		{
			if (Core.Get<ModStackSizes>().Configuration.Enabled)
			{
				List<ItemRegister> list = new List<ItemRegister>();
				Enumerator<ItemRegister> enumerator = __instance.ItemRegistry.GetEnumerator();
				while (enumerator.MoveNext())
				{
					ItemRegister current = enumerator.Current;
					list.Add(current);
				}
				ItemRegistry.AllItemDefinitions = list.Select((ItemRegister itemRegister) => itemRegister.Definition).ToList();
				ItemRegistry.UpdateEntireRegistry();
			}
		}
	}
}
namespace Lithium.Modules.PlantGrowth
{
	public class WeightedFloat
	{
		public float Weight;

		public float Value;

		[JsonConstructor]
		public WeightedFloat(float weight, float value)
		{
			Weight = weight;
			Value = value;
		}
	}
	public class PlantsPotsSection
	{
		[JsonProperty(Order = -10)]
		public string _Note = "POT-BASED PLANTS (Weed/Coca/Meth). GrowthSpeed: 1.0 = normal speed, 2.0 = 2x faster, 0.5 = 2x slower. WaterDrainModifier: soil drying speed — 1.0 = normal, 0.5 = dries 2x slower.";

		public float? GrowthSpeed = 1f;

		public float? WaterDrainModifier = 1f;
	}
	public class PlantsShroomsSection
	{
		[JsonProperty(Order = -10)]
		public string _Note = "MUSHROOMS (Mushroom Bed). GrowthSpeed: 1.0 = normal speed, 2.0 = 2x faster, 0.5 = 2x slower. WaterDrainModifier: substrate drying speed — 1.0 = normal, 0.5 = dries 2x slower.";

		public float? GrowthSpeed = 1f;

		public float? GrowthModifier;

		public float? WaterDrainModifier = 1f;
	}
	public class ModPlantsConfiguration : ModuleConfiguration
	{
		[JsonProperty(Order = -100)]
		public string _Note = "Lithium 'Plants' module — configure PLANTS (section 'Plants') and MUSHROOMS (section 'Shrooms') separately. The legacy GrowthModifier / WaterDrainModifier fields are used as a fallback when an explicit section value is not set.";

		public PlantsPotsSection Plants = new PlantsPotsSection();

		public PlantsShroomsSection Shrooms = new PlantsShroomsSection();

		public float GrowthModifier = 1f;

		public float WaterDrainModifier = 1f;

		public bool ShroomGrowContainersMatchNameOnly = true;

		public static readonly List<WeightedFloat> RandomYieldsPerBudModifierDefaults = new List<WeightedFloat>(3)
		{
			new WeightedFloat(7f, 1f),
			new WeightedFloat(2f, 2f),
			new WeightedFloat(1f, 3f)
		};

		public static readonly List<WeightedFloat> RandomYieldModifiersDefaults = new List<WeightedFloat>(4)
		{
			new WeightedFloat(7.5f, 1f),
			new WeightedFloat(1f, 0.25f),
			new WeightedFloat(1f, 1.5f),
			new WeightedFloat(0.5f, 3f)
		};

		public static readonly List<WeightedFloat> RandomQualityModifiersDefaults = new List<WeightedFloat>(5)
		{
			new WeightedFloat(0f, -0.5f),
			new WeightedFloat(0.5f, 0f),
			new WeightedFloat(0.75f, 0f),
			new WeightedFloat(0.2f, 0.4f),
			new WeightedFloat(0.01f, 0.5f)
		};

		public List<WeightedFloat> RandomYieldsPerBudModifier = RandomYieldsPerBudModifierDefaults;

		public List<WeightedFloat> RandomYieldModifiers = RandomYieldModifiersDefaults;

		public List<WeightedFloat> RandomQualityModifiers = RandomQualityModifiersDefaults;

		[JsonIgnore]
		public WeightedPicker<float> RandomYieldPerBudPicker;

		[JsonIgnore]
		public WeightedNormalizer RandomYieldModifierPicker;

		[JsonIgnore]
		public WeightedNormalizer RandomYieldQualityPicker;

		public override string Name => "Plants";

		internal float EffectivePotsGrowthModifier => Plants?.GrowthSpeed ?? GrowthModifier;

		internal float EffectivePotsWaterDrainModifier => Plants?.WaterDrainModifier ?? WaterDrainModifier;

		internal float EffectiveShroomGrowthModifier => Shrooms?.GrowthSpeed ?? Shrooms?.GrowthModifier ?? GrowthModifier;

		internal float EffectiveShroomWaterDrainModifier => Shrooms?.WaterDrainModifier ?? WaterDrainModifier;
	}
	public class ModPlants : ModuleBase<ModPlantsConfiguration>
	{
		public ModPlants()
		{
			ClassInjector.RegisterTypeInIl2Cpp<PlantModified>();
			ClassInjector.RegisterTypeInIl2Cpp<PlantBaseQuality>();
			ClassInjector.RegisterTypeInIl2Cpp<PotBaseValues>();
			ClassInjector.RegisterTypeInIl2Cpp<GrowContainerMoistureTracker>();
		}

		protected override void OnBeforeConfigurationLoaded()
		{
			base.OnBeforeConfigurationLoaded();
			base.Configuration.RandomYieldsPerBudModifier.Clear();
			base.Configuration.RandomYieldModifiers.Clear();
			base.Configuration.RandomQualityModifiers.Clear();
		}

		public override void Load()
		{
			base.Load();
			EnsureWeightedListsFromDefaults();
			RebuildWeightedPickers();
		}

		private void EnsureWeightedListsFromDefaults()
		{
			if (base.Configuration.RandomYieldsPerBudModifier.Count == 0)
			{
				foreach (WeightedFloat randomYieldsPerBudModifierDefault in ModPlantsConfiguration.RandomYieldsPerBudModifierDefaults)
				{
					base.Configuration.RandomYieldsPerBudModifier.Add(new WeightedFloat(randomYieldsPerBudModifierDefault.Weight, randomYieldsPerBudModifierDefault.Value));
				}
			}
			if (base.Configuration.RandomYieldModifiers.Count == 0 || base.Configuration.RandomYieldModifiers.Sum((WeightedFloat e) => e.Weight) <= 0f)
			{
				base.Configuration.RandomYieldModifiers.Clear();
				foreach (WeightedFloat randomYieldModifiersDefault in ModPlantsConfiguration.RandomYieldModifiersDefaults)
				{
					base.Configuration.RandomYieldModifiers.Add(new WeightedFloat(randomYieldModifiersDefault.Weight, randomYieldModifiersDefault.Value));
				}
			}
			if (base.Configuration.RandomQualityModifiers.Count != 0 && !(base.Configuration.RandomQualityModifiers.Sum((WeightedFloat e) => e.Weight) <= 0f))
			{
				return;
			}
			base.Configuration.RandomQualityModifiers.Clear();
			foreach (WeightedFloat randomQualityModifiersDefault in ModPlantsConfiguration.RandomQualityModifiersDefaults)
			{
				base.Configuration.RandomQualityModifiers.Add(new WeightedFloat(randomQualityModifiersDefault.Weight, randomQualityModifiersDefault.Value));
			}
		}

		private void RebuildWeightedPickers()
		{
			base.Configuration.RandomYieldPerBudPicker = new WeightedPicker<float>();
			base.Configuration.RandomYieldPerBudPicker.AddRange(base.Configuration.RandomYieldsPerBudModifier.Select((WeightedFloat p) => new KeyValuePair<float, float>(p.Value, p.Weight)));
			base.Configuration.RandomYieldModifierPicker = new WeightedNormalizer();
			foreach (WeightedFloat randomYieldModifier in base.Configuration.RandomYieldModifiers)
			{
				base.Configuration.RandomYieldModifierPicker.Add(randomYieldModifier.Weight, randomYieldModifier.Value);
			}
			base.Configuration.RandomYieldQualityPicker = new WeightedNormalizer();
			foreach (WeightedFloat randomQualityModifier in base.Configuration.RandomQualityModifiers)
			{
				base.Configuration.RandomYieldQualityPicker.Add(randomQualityModifier.Weight, randomQualityModifier.Value);
			}
		}

		public override void Apply()
		{
			_ = base.Configuration.Enabled;
		}
	}
}
namespace Lithium.Modules.PlantGrowth.Patches
{
	[HarmonyPatch(typeof(HarvestPotBehaviour), "OnActionSuccess")]
	public class HarvestPotBehaviourPatch
	{
		public static void Postfix(HarvestPotBehaviour __instance, ItemInstance usedItem)
		{
			ModPlantsConfiguration configuration = Core.Get<ModPlants>().Configuration;
			if (!configuration.Enabled)
			{
				return;
			}
			Botanist botanist = ((GrowContainerBehaviour)__instance)._botanist;
			if (!((Object)(object)botanist == (Object)null) && !((Object)(object)((NPC)botanist).Inventory == (Object)null))
			{
				ItemInstance itemToRetrieveTemplate = ((Employee)botanist).MoveItemBehaviour.itemToRetrieveTemplate;
				if (itemToRetrieveTemplate != null)
				{
					((BaseItemInstance)itemToRetrieveTemplate).Quantity = (int)Math.Min((float)((BaseItemInstance)itemToRetrieveTemplate).Quantity * configuration.RandomYieldPerBudPicker.Pick(), ((BaseItemInstance)itemToRetrieveTemplate).StackLimit);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Plant), "GrowthDone")]
	public class PlantGrowthDonePatch
	{
		[HarmonyPrefix]
		public static void Prefix(Plant __instance)
		{
			ModPlantsConfiguration configuration = Core.Get<ModPlants>().Configuration;
			if (configuration.Enabled && !((Object)(object)__instance == (Object)null) && !((Object)(object)((Component)__instance).GetComponent<PlantModified>() != (Object)null))
			{
				PlantModified plantModified = ((Component)__instance).gameObject.AddComponent<PlantModified>();
				plantModified.OriginalYieldLevel = __instance.YieldMultiplier;
				Plant val = ((Component)__instance).GetComponentInParent<Plant>();
				if ((Object)(object)val == (Object)null)
				{
					val = ((Component)__instance).GetComponent<Plant>();
				}
				if ((Object)(object)val != (Object)null)
				{
					plantModified.QualityLevel = val.QualityLevel;
				}
				__instance.YieldMultiplier *= configuration.RandomYieldModifierPicker.Evaluate(Random.value);
			}
		}
	}
	[HarmonyPatch(typeof(PlantHarvestable), "Harvest")]
	public class PlantHarvestablePatch
	{
		private static readonly Dictionary<object, bool> SkipFlags = new Dictionary<object, bool>();

		private static readonly Dictionary<object, bool> GenerateFlags = new Dictionary<object, bool>();

		[HarmonyPrefix]
		public static bool Prefix(PlantHarvestable __instance, bool giveProduct)
		{
			//IL_009d: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a2: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a8: Expected O, but got Unknown
			ModPlantsConfiguration configuration = Core.Get<ModPlants>().Configuration;
			if (!configuration.Enabled)
			{
				return true;
			}
			Plant componentInParent = ((Component)__instance).GetComponentInParent<Plant>();
			PlantBaseQuality plantBaseQuality = default(PlantBaseQuality);
			if (!((Component)componentInParent).TryGetComponent<PlantBaseQuality>(ref plantBaseQuality))
			{
				PlantBaseQuality plantBaseQuality2 = ((Component)componentInParent).gameObject.AddComponent<PlantBaseQuality>();
				plantBaseQuality2.Quality = componentInParent.QualityLevel;
				plantBaseQuality2.NeedsNotification = true;
			}
			if (!GenerateFlags.ContainsKey(__instance))
			{
				componentInParent.QualityLevel += configuration.RandomYieldQualityPicker.Evaluate(Random.value);
				__instance.ProductQuantity = (int)configuration.RandomYieldPerBudPicker.Pick();
				GenerateFlags[__instance] = true;
			}
			QualityItemInstance val = new QualityItemInstance((ItemDefinition)(object)__instance.Product, __instance.ProductQuantity, ItemQuality.GetQuality(componentInParent.QualityLevel));
			if (!PlayerSingleton<PlayerInventory>.Instance.CanItemFitInInventory((ItemInstance)(object)val, 1))
			{
				SkipFlags[__instance] = true;
				return false;
			}
			SkipFlags.Remove(__instance);
			return true;
		}

		[HarmonyPostfix]
		public static void Postfix(PlantHarvestable __instance)
		{
			//IL_0053: Unknown result type (might be due to invalid IL or missing references)
			//IL_0058: Unknown result type (might be due to invalid IL or missing references)
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			if (Core.Get<ModPlants>().Configuration.Enabled && !SkipFlags.ContainsKey(__instance) && GenerateFlags.Remove(__instance))
			{
				Plant componentInParent = ((Component)__instance).GetComponentInParent<Plant>();
				PlantBaseQuality plantBaseQuality = default(PlantBaseQuality);
				if (((Component)componentInParent).TryGetComponent<PlantBaseQuality>(ref plantBaseQuality) && plantBaseQuality.NeedsNotification)
				{
					EQuality quality = ItemQuality.GetQuality(componentInParent.QualityLevel);
					Singleton<NotificationsManager>.Instance.SendNotification($"{__instance.ProductQuantity}x {((BaseItemDefinition)componentInParent.SeedDefinition).Name}", $"{quality:G} quality", ((BaseItemDefinition)componentInParent.SeedDefinition).Icon, 2f, false);
					componentInParent.QualityLevel = plantBaseQuality.Quality;
					plantBaseQuality.NeedsNotification = false;
					Object.Destroy((Object)(object)plantBaseQuality);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Pot), "GetTemperatureGrowthMultiplier")]
	public class PotPatch
	{
		[HarmonyPostfix]
		public static void Postfix(ref float __result)
		{
			ModPlantsConfiguration configuration = Core.Get<ModPlants>().Configuration;
			if (configuration.Enabled)
			{
				float effectivePotsGrowthModifier = configuration.EffectivePotsGrowthModifier;
				if (effectivePotsGrowthModifier <= 0.001f)
				{
					MelonLogger.Error("[Lithium_fork][Plants] Plants.GrowthSpeed (or root GrowthModifier) is invalid (<= 0). Skipping patch.");
				}
				else
				{
					__result *= Mathf.Max(0.001f, effectivePotsGrowthModifier);
				}
			}
		}
	}
	[HarmonyPatch(typeof(Pot), "Start")]
	public class PotStartPatch
	{
		[HarmonyPostfix]
		public static void Postfix(Pot __instance)
		{
			if (Core.Get<ModPlants>().Configuration.Enabled)
			{
				((Component)__instance).gameObject.AddComponent<PotBaseValues>().Init(__instance);
			}
		}
	}
	[HarmonyPatch(typeof(Pot), "OnMinPass")]
	public class PotMinPassPatch
	{
		[HarmonyPrefix]
		public static void Prefix(Pot __instance)
		{
			if (Core.Get<ModPlants>().Configuration.Enabled && !((Object)(object)__instance == (Object)null))
			{
				PotBaseValues component = ((Component)__instance).gameObject.GetComponent<PotBaseValues>();
				if (!((Object)(object)component == (Object)null))
				{
					float baseWaterDrainPerHour = component.BaseWaterDrainPerHour;
					((GrowContainer)__instance)._moistureDrainPerHour = baseWaterDrainPerHour * Core.Get<ModPlants>().Configuration.EffectivePotsWaterDrainModifier;
				}
			}
		}
	}
	internal static class GrowContainerShroomHarmony
	{
		internal static void Apply(Harmony harmony)
		{
			//IL_01ff: Unknown result type (might be due to invalid IL or missing references)
			//IL_020d: Expected O, but got Unknown
			ModPlants modPlants = Core.Get<ModPlants>();
			if (modPlants?.Configuration == null || !modPlants.Configuration.Enabled)
			{
				MelonLogger.Msg("[Lithium_fork][Plants] Plants module disabled — shroom hooks skipped (set Plants.json Enabled=true to activate).");
				return;
			}
			Type typeFromHandle = typeof(GrowContainer);
			Type typeFromHandle2 = typeof(Pot);
			Assembly assembly = typeFromHandle.Assembly;
			Type[] array;
			try
			{
				array = assembly.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				array = ex.Types?.Where((Type t) => t != null).Cast<Type>().ToArray() ?? Array.Empty<Type>();
			}
			List<Type> list = new List<Type>();
			Type[] array2 = array;
			foreach (Type type in array2)
			{
				if (!(type == null) && !type.IsAbstract && typeFromHandle.IsAssignableFrom(type) && !(type == typeFromHandle2) && (!modPlants.Configuration.ShroomGrowContainersMatchNameOnly || LikelyShroomRelatedTypeName(type.Name)))
				{
					list.Add(type);
				}
			}
			MelonLogger.Msg($"[Lithium_fork][Plants] Shroom GrowContainer scan: {list.Count} candidate type(s) found.");
			int num = 0;
			int num2 = 0;
			int num3 = 0;
			foreach (Type item in list)
			{
				num += TryPatchDeclared(harmony, item, "GetTemperatureGrowthMultiplier", "GrowthPostfix", requireFloatNoArgs: true, null);
				num2 += TryPatchDeclared(harmony, item, "GetCurrentGrowthRate", "GrowthRatePostfix", requireFloatNoArgs: true, null);
				num3 += TryPatchDeclared(harmony, item, "OnMinPass", null, requireFloatNoArgs: false, "OnMinPassPrefix");
			}
			int value = 0;
			try
			{
				MethodInfo methodInfo = AccessTools.DeclaredMethod(typeof(GrowContainer), "OnMinPass", (Type[])null, (Type[])null);
				if (methodInfo != null)
				{
					harmony.Patch((MethodBase)methodInfo, new HarmonyMethod(typeof(GrowContainerShroomHarmony), "OnMinPassPrefix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					value = 1;
				}
			}
			catch (Exception ex2)
			{
				MelonLogger.Warning("[Lithium_fork][Plants] Could not patch GrowContainer.OnMinPass (base): " + ex2.Message);
			}
			MelonLogger.Msg($"[Lithium_fork][Plants] Shroom patches applied: GetTemperatureGrowthMultiplier={num}, GetCurrentGrowthRate={num2}, OnMinPass(declared)={num3}, OnMinPass(base)={value}.");
			MelonLogger.Msg($"[Lithium_fork][Plants] Shroom config in use: GrowthSpeed={modPlants.Configuration.EffectiveShroomGrowthModifier:F3}, WaterDrain={modPlants.Configuration.EffectiveShroomWaterDrainModifier:F3}.");
		}

		private static int TryPatchDeclared(Harmony harmony, Type t, string methodName, string postfix, bool requireFloatNoArgs, string prefix)
		{
			//IL_0050: Unknown result type (might be due to invalid IL or missing references)
			//IL_0068: Unknown result type (might be due to invalid IL or missing references)
			MethodInfo methodInfo = AccessTools.DeclaredMethod(t, methodName, (Type[])null, (Type[])null);
			if (methodInfo == null)
			{
				return 0;
			}
			if (requireFloatNoArgs && (methodInfo.ReturnType != typeof(float) || methodInfo.GetParameters().Length != 0))
			{
				return 0;
			}
			try
			{
				HarmonyMethod val = ((prefix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(GrowContainerShroomHarmony), prefix, (Type[])null));
				HarmonyMethod val2 = ((postfix == null) ? ((HarmonyMethod)null) : new HarmonyMethod(typeof(GrowContainerShroomHarmony), postfix, (Type[])null));
				harmony.Patch((MethodBase)methodInfo, val, val2, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
				MelonLogger.Msg($"[Lithium_fork][Plants]   patched {t.FullName}.{methodName} ({((val != null) ? "prefix" : "")}{((val != null && val2 != null) ? "+" : "")}{((val2 != null) ? "postfix" : "")}).");
				return 1;
			}
			catch (Exception ex)
			{
				MelonLogger.Warning($"[Lithium_fork][Plants]   patch failed: {t.FullName}.{methodName}: {ex.Message}");
				return 0;
			}
		}

		private static bool LikelyShroomRelatedTypeName(string typeName)
		{
			if (string.IsNullOrEmpty(typeName))
			{
				return false;
			}
			if (typeName.IndexOf("Mushroom", StringComparison.OrdinalIgnoreCase) < 0 && typeName.IndexOf("Substrate", StringComparison.OrdinalIgnoreCase) < 0 && typeName.IndexOf("Fungal", StringComparison.OrdinalIgnoreCase) < 0 && typeName.IndexOf("Shroom", StringComparison.OrdinalIgnoreCase) < 0 && typeName.IndexOf("Mycelium", StringComparison.OrdinalIgnoreCase) < 0 && typeName.IndexOf("MonoTub", StringComparison.OrdinalIgnoreCase) < 0 && typeName.IndexOf("SpawnStation", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return typeName.IndexOf("Colony", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private static void GrowthPostfix(GrowContainer __instance, ref float __result)
		{
			ScaleGrowthResult(__instance, ref __result);
		}

		private static void GrowthRatePostfix(GrowContainer __instance, ref float __result)
		{
			ScaleGrowthResult(__instance, ref __result);
		}

		private static void ScaleGrowthResult(GrowContainer __instance, ref float __result)
		{
			ModPlantsConfiguration modPlantsConfiguration = Core.Get<ModPlants>()?.Configuration;
			if (modPlantsConfiguration == null || !modPlantsConfiguration.Enabled)
			{
				return;
			}
			try
			{
				if (__instance is Pot)
				{
					return;
				}
			}
			catch
			{
			}
			if (!modPlantsConfiguration.ShroomGrowContainersMatchNameOnly || LikelyShroomRelatedTypeName(((object)__instance).GetType().Name))
			{
				float effectiveShroomGrowthModifier = modPlantsConfiguration.EffectiveShroomGrowthModifier;
				if (effectiveShroomGrowthModifier <= 0.001f)
				{
					MelonLogger.Error("[Lithium_fork][Plants] Invalid Shroom growth modifier. Skipping (set Plants.Shrooms.GrowthSpeed > 0).");
				}
				else
				{
					__result *= Mathf.Max(0.001f, effectiveShroomGrowthModifier);
				}
			}
		}

		private static void OnMinPassPrefix(GrowContainer __instance)
		{
			ModPlantsConfiguration modPlantsConfiguration = Core.Get<ModPlants>()?.Configuration;
			if (modPlantsConfiguration == null || !modPlantsConfiguration.Enabled)
			{
				return;
			}
			try
			{
				if (__instance is Pot)
				{
					return;
				}
			}
			catch
			{
			}
			if (!modPlantsConfiguration.ShroomGrowContainersMatchNameOnly || LikelyShroomRelatedTypeName(((object)__instance).GetType().Name))
			{
				GrowContainerMoistureTracker growContainerMoistureTracker = ((Component)__instance).gameObject.GetComponent<GrowContainerMoistureTracker>();
				if ((Object)(object)growContainerMoistureTracker == (Object)null)
				{
					growContainerMoistureTracker = ((Component)__instance).gameObject.AddComponent<GrowContainerMoistureTracker>();
					growContainerMoistureTracker.BaseDrainPerHour = __instance._moistureDrainPerHour;
				}
				float effectiveShroomWaterDrainModifier = modPlantsConfiguration.EffectiveShroomWaterDrainModifier;
				if (!(effectiveShroomWaterDrainModifier <= 0.001f))
				{
					__instance._moistureDrainPerHour = growContainerMoistureTracker.BaseDrainPerHour * Mathf.Max(0.001f, effectiveShroomWaterDrainModifier);
				}
			}
		}
	}
}
namespace Lithium.Modules.PlantGrowth.Behaviours
{
	public class PlantBaseQuality : MonoBehaviour
	{
		public float Quality;

		public bool NeedsNotification;
	}
	public class PlantModified : MonoBehaviour
	{
		public float OriginalYieldLevel;

		public float QualityLevel;
	}
	public class PotBaseValues : MonoBehaviour
	{
		public float BaseWaterDrainPerHour;

		public void Init(Pot pot)
		{
			BaseWaterDrainPerHour = ((GrowContainer)pot)._moistureDrainPerHour;
		}
	}
	public class GrowContainerMoistureTracker : MonoBehaviour
	{
		public float BaseDrainPerHour;
	}
}
namespace Lithium.Modules.Storyline
{
	public class ModStorylineConfiguration : ModuleConfiguration
	{
		public override string Name => "Storyline";

		public bool PreventRVExplosion { get; set; } = true;

	}
	public class ModStoryline : ModuleBase<ModStorylineConfiguration>
	{
		public override void Apply()
		{
			_ = base.Configuration.Enabled;
		}
	}
}
namespace Lithium.Modules.Storyline.Patches
{
	[HarmonyPatch(typeof(RV), "SetDestroyed")]
	public class RVSetExplodedPatch
	{
		[HarmonyPrefix]
		public static bool DisableRVExplosion(RV __instance)
		{
			ModStorylineConfiguration configuration = Core.Get<ModStoryline>().Configuration;
			if (!configuration.Enabled || !configuration.PreventRVExplosion)
			{
				return true;
			}
			GameObject childGameObject = GetChildGameObject(((Component)__instance).gameObject, "Destroyed RV");
			if ((Object)(object)childGameObject != (Object)null)
			{
				childGameObject.SetActive(true);
				GameObject childGameObject2 = GetChildGameObject(childGameObject, "CartelNote");
				if ((Object)(object)childGameObject2 != (Object)null)
				{
					childGameObject2.SetActive(true);
				}
				GameObject childGameObject3 = GetChildGameObject(childGameObject, "destroyed rv");
				if ((Object)(object)childGameObject3 != (Object)null)
				{
					childGameObject3.SetActive(false);
				}
			}
			else
			{
				MelonLogger.Msg("Destroyed RV not found");
			}
			return false;
		}

		private static GameObject GetChildGameObject(GameObject obj, string childName)
		{
			Transform val = obj.transform.Find(childName);
			if (!((Object)(object)val != (Object)null))
			{
				return null;
			}
			return ((Component)val).gameObject;
		}
	}
	[HarmonyPatch(typeof(Quest_WelcomeToHylandPoint), "BlowupRV")]
	public class QuestWelcomeToHylandPointPatch
	{
		[HarmonyPrefix]
		public static bool DisableRVExplosion(Quest_WelcomeToHylandPoint __instance)
		{
			ModStorylineConfiguration configuration = Core.Get<ModStoryline>().Configuration;
			if (!configuration.Enabled || !configuration.PreventRVExplosion)
			{
				return true;
			}
			return false;
		}
	}
}
namespace Lithium.Modules.Shops
{
	internal static class SupplierPhoneListingPriceHelper
	{
		private const BindingFlags InstanceAny = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		internal static void ApplyListingPriceFieldsOnly(Listing listing, float price)
		{
			if (listing == null)
			{
				return;
			}
			Type type = ((object)listing).GetType();
			while (type != null && type != typeof(object))
			{
				string[] array = new string[4] { "Price", "price", "_price", "<Price>k__BackingField" };
				foreach (string name in array)
				{
					FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
					if (!(field == null) && !(field.FieldType != typeof(float)))
					{
						try
						{
							field.SetValue(listing, price);
						}
						catch
						{
						}
					}
				}
				type = type.BaseType;
			}
		}
	}
	internal static class PhoneShopInterfaceListingsHelper
	{
		private static readonly string[] PreferredMemberNames = new string[8] { "Listings", "listings", "ShopListings", "shopListings", "OnlineShopListings", "onlineShopListings", "ActiveListings", "activeListings" };

		private const BindingFlags InstanceAny = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;

		internal static IEnumerable<Listing> EnumerateListings(PhoneShopInterface psi)
		{
			if ((Object)(object)psi == (Object)null)
			{
				yield break;
			}
			Type t = typeof(PhoneShopInterface);
			string[] preferredMemberNames = PreferredMemberNames;
			foreach (string name in preferredMemberNames)
			{
				PropertyInfo property = t.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (property != null && property.GetIndexParameters().Length == 0)
				{
					object obj;
					try
					{
						obj = property.GetValue(psi);
					}
					catch
					{
						obj = null;
					}
					if (obj != null)
					{
						foreach (Listing item in EnumerateFromValue(obj))
						{
							yield return item;
						}
						yield break;
					}
				}
				FieldInfo field = t.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				if (!(field != null))
				{
					continue;
				}
				object obj3;
				try
				{
					obj3 = field.GetValue(psi);
				}
				catch
				{
					obj3 = null;
				}
				if (obj3 == null)
				{
					continue;
				}
				foreach (Listing item2 in EnumerateFromValue(obj3))
				{
					yield return item2;
				}
				yield break;
			}
			PropertyInfo[] properties = t.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (PropertyInfo propertyInfo in properties)
			{
				if (propertyInfo.GetIndexParameters().Length != 0 || !LooksLikeListingCollectionName(propertyInfo.Name))
				{
					continue;
				}
				foreach (Listing item3 in EnumerateFromMember(psi, propertyInfo))
				{
					yield return item3;
				}
			}
			FieldInfo[] fields = t.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (FieldInfo fieldInfo in fields)
			{
				if (!LooksLikeListingCollectionName(fieldInfo.Name))
				{
					continue;
				}
				foreach (Listing item4 in EnumerateFromField(psi, fieldInfo))
				{
					yield return item4;
				}
			}
		}

		private static bool LooksLikeListingCollectionName(string name)
		{
			if (string.IsNullOrEmpty(name))
			{
				return false;
			}
			return name.IndexOf("listing", StringComparison.OrdinalIgnoreCase) >= 0;
		}

		private static IEnumerable<Listing> EnumerateFromMember(PhoneShopInterface psi, PropertyInfo pi)
		{
			object value;
			try
			{
				value = pi.GetValue(psi);
			}
			catch
			{
				yield break;
			}
			foreach (Listing item in EnumerateFromValue(value))
			{
				yield return item;
			}
		}

		private static IEnumerable<Listing> EnumerateFromField(PhoneShopInterface psi, FieldInfo fi)
		{
			object value;
			try
			{
				value = fi.GetValue(psi);
			}
			catch
			{
				yield break;
			}
			foreach (Listing item in EnumerateFromValue(value))
			{
				yield return item;
			}
		}

		private static IEnumerable<Listing> EnumerateFromValue(object raw)
		{
			if (raw == null)
			{
				yield break;
			}
			if (raw is Array array)
			{
				foreach (object item in array)
				{
					Listing val = (Listing)((item is Listing) ? item : null);
					if (val != null)
					{
						yield return val;
					}
				}
			}
			else
			{
				if (!(raw is IEnumerable enumerable))
				{
					yield break;
				}
				foreach (object item2 in enumerable)
				{
					Listing val2 = (Listing)((item2 is Listing) ? item2 : null);
					if (val2 != null)
					{
						yield return val2;
					}
				}
			}
		}

		internal static void TryInvokeListingOrPriceRefresh(PhoneShopInterface psi)
		{
			if ((Object)(object)psi == (Object)null)
			{
				return;
			}
			Type typeFromHandle = typeof(PhoneShopInterface);
			string[] array = new string[6] { "Refresh", "RefreshListings", "RefreshPrices", "UpdatePrices", "RebuildListings", "UpdateListings" };
			foreach (string name in array)
			{
				MethodInfo method = typeFromHandle.GetMethod(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic, null, Type.EmptyTypes, null);
				if (!(method == null))
				{
					try
					{
						method.Invoke(psi, null);
						break;
					}
					catch
					{
						break;
					}
				}
			}
		}
	}
	public class SupplierListingOverride
	{
		public Dictionary<string, float> PriceOverrides { get; set; } = new Dictionary<string, float>();

	}
	public class ItemListingOverride
	{
		public float Price { get; set; }

		[JsonConverter(typeof(StringEnumConverter))]
		public ERestockRate RestockRate { get; set; }

		public int Stock { get; set; } = -1;

	}
	public class ShopListingSettings
	{
		[JsonProperty(Order = 6)]
		public Dictionary<string, ItemListingOverride> ItemOverrides = new Dictionary<string, ItemListingOverride>();

		[JsonProperty(Order = 1)]
		public bool Override { get; set; }

		[JsonProperty(Order = 2)]
		public int DefaultStock { get; set; } = -1;


		[JsonConverter(typeof(StringEnumConverter))]
		[JsonProperty(Order = 3)]
		public EPaymentType PaymentType { get; set; }
	}
	public enum DeliveryAvailabilitySettings
	{
		Unchanged,
		Never,
		Always,
		AfterReachingXP
	}
	public class DeliverySettings
	{
		[JsonConverter(typeof(StringEnumConverter))]
		public DeliveryAvailabilitySettings Availability { get; set; }

		public float DeliveryFee { get; set; } = 200f;


		public int XPRequirement { get; set; }
	}
	public class ModShopsConfiguration : ModuleConfiguration
	{
		public ShopListingSettings ThriftyThreads;

		public ShopListingSettings CokeSupplier;

		public ShopListingSettings MethSupplier;

		public ShopListingSettings WeedSupplier;

		public ShopListingSettings ShroomsSupplier;

		public ShopListingSettings Boutique;

		public ShopListingSettings DarkMarket;

		public ShopListingSettings GasStation;

		public ShopListingSettings CentralGasStation;

		public ShopListingSettings DansHardware;

		public ShopListingSettings HandyHanks;

		public ShopListingSettings ArmsDealer;

		public SupplierListingOverride Albert;

		public SupplierListingOverride Shirley;

		public SupplierListingOverride Salvador;

		public SupplierListingOverride Fungal;

		public override string Name => "Shops";

		[JsonProperty(Order = -450)]
		public bool PhoneMirrorListingPriceFields { get; set; }

		public Dictionary<string, DeliverySettings> Deliveries { get; set; }
	}
	public class ModShops : ModuleBase<ModShopsConfiguration>
	{
		public override void Apply()
		{
		}
	}
}
namespace Lithium.Modules.Shops.Patches
{
	[HarmonyPatch(typeof(ShopInterface), "SetIsOpen")]
	public class ForceUpdateShopPrices
	{
		[HarmonyPostfix]
		public static void ShopInterfaceSetIsOpen(ShopInterface __instance, bool isOpen)
		{
			if (isOpen && Core.Get<ModShops>().Configuration.Enabled)
			{
				SupplierStartPatch.ProcessShopInterface(__instance);
			}
			Enumerator<ListingUI> enumerator = __instance.listingUI.GetEnumerator();
			while (enumerator.MoveNext())
			{
				ListingUI current = enumerator.Current;
				current.UpdateLockStatus();
				current.Update();
				current.UpdatePrice();
				current.UpdateStock();
				current.UpdateButtons();
			}
		}
	}
	[HarmonyPatch(typeof(Player), "NetworkInitialize__Late")]
	public class SupplierStartPatch
	{
		private static bool _deferredUiSupplierApplyScheduled;

		private static readonly Dictionary<string, int> LastAppliedStockByListing = new Dictionary<string, int>();

		[HarmonyPrefix]
		public static void PatchPrices()
		{
			ModShopsConfiguration configuration = Core.Get<ModShops>().Configuration;
			if (configuration.Enabled)
			{
				ApplyShopOverrides();
				ApplySupplierOverrides();
				configuration.SaveConfiguration();
			}
		}

		public static void ApplySupplierOverridesFromUiHooks()
		{
			ModShops modShops = Core.Get<ModShops>();
			if (modShops != null && modShops.Configuration.Enabled && !_deferredUiSupplierApplyScheduled)
			{
				_deferredUiSupplierApplyScheduled = true;
				MelonCoroutines.Start(DeferredUiSupplierApplyCoroutine());
			}
		}

		private static IEnumerator DeferredUiSupplierApplyCoroutine()
		{
			yield return null;
			_deferredUiSupplierApplyScheduled = false;
			ApplySupplierOverrides();
			yield return (object)new WaitForEndOfFrame();
			ApplySupplierOverrides();
		}

		public static void ApplySupplierOverrides()
		{
			ModShopsConfiguration configuration = Core.Get<ModShops>().Configuration;
			if (!configuration.Enabled)
			{
				return;
			}
			Albert val = ((IEnumerable<Albert>)Object.FindObjectsOfType<Albert>(true)).FirstOrDefault();
			if ((Object)(object)val != (Object)null)
			{
				AssertSupplierConfigEntryExists(ref configuration.Albert, (Supplier)(object)val);
				if (configuration.Albert != null)
				{
					ApplySupplierConfigValues(configuration.Albert, (Supplier)(object)val);
				}
			}
			Shirley val2 = ((IEnumerable<Shirley>)Object.FindObjectsOfType<Shirley>(true)).FirstOrDefault();
			if ((Object)(object)val2 != (Object)null)
			{
				AssertSupplierConfigEntryExists(ref configuration.Shirley, (Supplier)(object)val2);
				if (configuration.Shirley != null)
				{
					ApplySupplierConfigValues(configuration.Shirley, (Supplier)(object)val2);
				}
			}
			Salvador val3 = ((IEnumerable<Salvador>)Object.FindObjectsOfType<Salvador>(true)).FirstOrDefault();
			if ((Object)(object)val3 != (Object)null)
			{
				AssertSupplierConfigEntryExists(ref configuration.Salvador, (Supplier)(object)val3);
				if (configuration.Salvador != null)
				{
					ApplySupplierConfigValues(configuration.Salvador, (Supplier)(object)val3);
				}
			}
			TryApplyFungalPhoneSupplier(configuration);
			TryApplyFungalPhoneShopInterfaceModals(configuration);
		}

		private static void AssertSupplierConfigEntryExists(ref SupplierListingOverride configuration, Supplier supplier)
		{
			if (supplier.OnlineShopItems != null && configuration == null)
			{
				configuration = new SupplierListingOverride
				{
					PriceOverrides = ((IEnumerable<Listing>)supplier.OnlineShopItems).Where((Listing listing) => (Object)(object)((listing != null) ? listing.Item : null) != (Object)null).ToDictionary((Listing listing) => ((BaseItemDefinition)listing.Item).ID, (Listing listing) => listing.Price)
				};
			}
		}

		private static void ApplySupplierConfigValues(SupplierListingOverride configuration, Supplier supplier)
		{
			if (configuration?.PriceOverrides == null || ((supplier != null) ? supplier.OnlineShopItems : null) == null)
			{
				return;
			}
			foreach (Listing item in (Il2CppArrayBase<Listing>)(object)supplier.OnlineShopItems)
			{
				if (!((Object)(object)((item != null) ? item.Item : null) == (Object)null) && configuration.PriceOverrides.TryGetValue(((BaseItemDefinition)item.Item).ID, out var value))
				{
					item.Item.BasePurchasePrice = value;
					ModShops modShops = Core.Get<ModShops>();
					if (modShops != null && modShops.Configuration.PhoneMirrorListingPriceFields)
					{
						SupplierPhoneListingPriceHelper.ApplyListingPriceFieldsOnly(item, value);
					}
				}
			}
		}

		private static void TryApplyFungalPhoneSupplier(ModShopsConfiguration configuration)
		{
			Type typeFromHandle = typeof(Albert);
			Type typeFromHandle2 = typeof(Shirley);
			Type typeFromHandle3 = typeof(Salvador);
			foreach (Supplier item in Object.FindObjectsOfType<Supplier>(true))
			{
				if ((Object)(object)item == (Object)null)
				{
					continue;
				}
				Type type = ((object)item).GetType();
				if (!(type == typeFromHandle) && !(type == typeFromHandle2) && !(type == typeFromHandle3) && (SupplierNameLooksLikeFungal(item) || SupplierCatalogMatchesFungalJson(configuration.Fungal, item)))
				{
					AssertSupplierConfigEntryExists(ref configuration.Fungal, item);
					if (configuration.Fungal != null)
					{
						ApplySupplierConfigValues(configuration.Fungal, item);
					}
				}
			}
		}

		private static bool SupplierNameLooksLikeFungal(Supplier supplier)
		{
			string obj = ((object)supplier).GetType().Name ?? string.Empty;
			string text = (((Object)(object)((Component)supplier).gameObject != (Object)null) ? ((Object)((Component)supplier).gameObject).name : string.Empty);
			if (obj.IndexOf("Fungal", StringComparison.OrdinalIgnoreCase) < 0)
			{
				return text.IndexOf("Fungal", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return true;
		}

		private static bool SupplierCatalogMatchesFungalJson(SupplierListingOverride fungal, Supplier supplier)
		{
			if (fungal?.PriceOverrides == null || fungal.PriceOverrides.Count == 0)
			{
				return false;
			}
			if (((supplier != null) ? supplier.OnlineShopItems : null) == null)
			{
				return false;
			}
			List<string> list = (from l in (IEnumerable<Listing>)supplier.OnlineShopItems
				where (Object)(object)((l != null) ? l.Item : null) != (Object)null
				select ((BaseItemDefinition)l.Item).ID).ToList();
			if (list.Count == 0)
			{
				return false;
			}
			int num = list.Count((string id) => fungal.PriceOverrides.ContainsKey(id));
			if (num >= 2)
			{
				return true;
			}
			if (num >= 1)
			{
				return num == list.Count;
			}
			return false;
		}

		private static void TryApplyFungalPhoneShopInterfaceModals(ModShopsConfiguration configuration)
		{
			SupplierListingOverride fungal = configuration.Fungal;
			if (fungal?.PriceOverrides == null || fungal.PriceOverrides.Count == 0)
			{
				return;
			}
			foreach (PhoneShopInterface item in Object.FindObjectsOfType<PhoneShopInterface>(true))
			{
				if ((Object)(object)item == (Object)null || !PhoneShopInterfaceLooksLikeFungalModal(fungal, item))
				{
					continue;
				}
				foreach (Listing item2 in PhoneShopInterfaceListingsHelper.EnumerateListings(item))
				{
					if (!((Object)(object)((item2 != null) ? item2.Item : null) == (Object)null) && fungal.PriceOverrides.TryGetValue(((BaseItemDefinition)item2.Item).ID, out var value))
					{
						item2.Item.BasePurchasePrice = value;
						if (configuration.PhoneMirrorListingPriceFields)
						{
							SupplierPhoneListingPriceHelper.ApplyListingPriceFieldsOnly(item2, value);
						}
					}
				}
				PhoneShopInterfaceListingsHelper.TryInvokeListingOrPriceRefresh(item);
			}
		}

		private static bool PhoneShopInterfaceLooksLikeFungalModal(SupplierListingOverride fungal, PhoneShopInterface psi)
		{
			List<string> list = new List<string>();
			foreach (Listing item in PhoneShopInterfaceListingsHelper.EnumerateListings(psi))
			{
				if ((Object)(object)((item != null) ? item.Item : null) != (Object)null)
				{
					list.Add(((BaseItemDefinition)item.Item).ID);
				}
			}
			if (list.Count == 0)
			{
				return false;
			}
			int num = list.Count((string id) => fungal.PriceOverrides.ContainsKey(id));
			if (num >= 2)
			{
				return true;
			}
			if (num >= 1)
			{
				return num == list.Count;
			}
			return false;
		}

		private static void ApplyShopOverrides()
		{
			List<ShopInterface> list = ((IEnumerable<ShopInterface>)Object.FindObjectsOfType<ShopInterface>()).ToList();
			MelonLogger.Msg($"[Lithium_fork][Shops] ApplyShopOverrides: {list.Count} ShopInterface(s): " + string.Join(", ", from s in list
				where (Object)(object)s != (Object)null
				select s.ShopCode ?? "?"));
			foreach (ShopInterface item in list)
			{
				ProcessShopInterface(item);
			}
		}

		public static void ProcessShopInterface(ShopInterface shopInterface)
		{
			if ((Object)(object)shopInterface == (Object)null)
			{
				return;
			}
			ModShopsConfiguration configuration = Core.Get<ModShops>().Configuration;
			List<ShopListing> list = shopInterface.Listings?.ToList<ShopListing>();
			if (list == null)
			{
				return;
			}
			string shopCode = shopInterface.ShopCode;
			if (shopCode == null)
			{
				return;
			}
			switch (shopCode.Length)
			{
			case 9:
				switch (shopCode[0])
				{
				case 'c':
					if (shopCode == "coke_shop")
					{
						AssertConfigurationEntries(ref configuration.CokeSupplier, shopInterface, list);
						if (configuration.Enabled)
						{
							ApplyShopSettings(list, shopInterface, configuration.CokeSupplier);
						}
					}
					break;
				case 'm':
					if (shopCode == "meth_shop")
					{
						AssertConfigurationEntries(ref configuration.MethSupplier, shopInterface, list);
						if (configuration.Enabled)
						{
							ApplyShopSettings(list, shopInterface, configuration.MethSupplier);
						}
					}
					break;
				case 'w':
					if (shopCode == "weed_shop")
					{
						AssertConfigurationEntries(ref configuration.WeedSupplier, shopInterface, list);
						if (configuration.Enabled)
						{
							ApplyShopSettings(list, shopInterface, configuration.WeedSupplier);
						}
					}
					break;
				}
				break;
			case 16:
				switch (shopCode[0])
				{
				case 'd':
					if (shopCode == "dark_market_shop")
					{
						ApplyDarkMarketFromConfig(configuration, shopInterface, list);
					}
					break;
				case 'g':
					if (shopCode == "gas_mart_central")
					{
						AssertConfigurationEntries(ref configuration.CentralGasStation, shopInterface, list);
						if (configuration.Enabled)
						{
							ApplyShopSettings(list, shopInterface, configuration.CentralGasStation);
						}
					}
					break;
				}
				break;
			case 13:
				switch (shopCode[0])
				{
				case 'g':
					if (shopCode == "gas_mart_west")
					{
						AssertConfigurationEntries(ref configuration.GasStation, shopInterface, list);
						if (configuration.Enabled)
						{
							ApplyShopSettings(list, shopInterface, configuration.GasStation);
						}
					}
					break;
				case 'd':
					if (shopCode == "dans_hardware")
					{
						AssertConfigurationEntries(ref configuration.DansHardware, shopInterface, list);
						if (configuration.Enabled)
						{
							ApplyShopSettings(list, shopInterface, configuration.DansHardware);
						}
					}
					break;
				}
				break;
			case 15:
				if (shopCode == "thrifty_threads")
				{
					AssertConfigurationEntries(ref configuration.ThriftyThreads, shopInterface, list);
					if (configuration.Enabled)
					{
						ApplyShopSettings(list, shopInterface, configuration.ThriftyThreads);
					}
				}
				break;
			case 12:
				if (shopCode == "shrooms_shop")
				{
					AssertConfigurationEntries(ref configuration.ShroomsSupplier, shopInterface, list);
					if (configuration.Enabled)
					{
						ApplyShopSettings(list, shopInterface, configuration.ShroomsSupplier);
					}
				}
				break;
			case 8:
				if (shopCode == "boutique")
				{
					AssertConfigurationEntries(ref configuration.Boutique, shopInterface, list);
					if (configuration.Enabled)
					{
						ApplyShopSettings(list, shopInterface, configuration.Boutique);
					}
				}
				break;
			case 4:
				if (shopCode == "shop" && IsDarkMarketShopInterface(shopInterface))
				{
					ApplyDarkMarketFromConfig(configuration, shopInterface, list);
				}
				break;
			case 11:
				if (shopCode == "handy_hanks")
				{
					AssertConfigurationEntries(ref configuration.HandyHanks, shopInterface, list);
					if (configuration.Enabled)
					{
						ApplyShopSettings(list, shopInterface, configuration.HandyHanks);
					}
				}
				break;
			case 10:
				if (shopCode == "armsdealer")
				{
					AssertConfigurationEntries(ref configuration.ArmsDealer, shopInterface, list);
					if (configuration.Enabled)
					{
						ApplyShopSettings(list, shopInterface, configuration.ArmsDealer);
					}
				}
				break;
			case 5:
			case 6:
			case 7:
			case 14:
				break;
			}
		}

		private static bool IsDarkMarketShopInterface(ShopInterface shopInterface)
		{
			if ((Object)(object)((Component)shopInterface).gameObject != (Object)null)
			{
				return ((Object)((Component)shopInterface).gameObject).name.IndexOf("DarkMarket", StringComparison.OrdinalIgnoreCase) >= 0;
			}
			return false;
		}

		private static void ApplyDarkMarketFromConfig(ModShopsConfiguration configuration, ShopInterface shopInterface, List<ShopListing> listings)
		{
			AssertConfigurationEntries(ref configuration.DarkMarket, shopInterface, listings);
			if (configuration.Enabled)
			{
				ApplyShopSettings(listings, shopInterface, configuration.DarkMarket);
			}
		}

		private static void AssertConfigurationEntries(ref ShopListingSettings configSetting, ShopInterface shopInterface, List<ShopListing> listings)
		{
			//IL_001a: Unknown result type (might be due to invalid IL or missing references)
			if (configSetting == null)
			{
				configSetting = new ShopListingSettings
				{
					Override = false,
					DefaultStock = -1,
					PaymentType = shopInterface.PaymentType,
					ItemOverrides = listings.ToDictionary((ShopListing listing) => ((BaseItemDefinition)listing.Item).ID, (ShopListing listing) => new ItemListingOverride
					{
						Price = listing.Price,
						Stock = (listing.LimitedStock ? listing.DefaultStock : (-1)),
						RestockRate = listing.RestockRate
					})
				};
			}
			shopInterface.RefreshShownItems();
			shopInterface.RefreshUnlockStatus();
		}

		private static string ListingStockKey(ShopInterface shopInterface, ShopListing listing)
		{
			string obj = (((Object)(object)shopInterface != (Object)null && shopInterface.ShopCode != null) ? shopInterface.ShopCode : "?");
			object obj2;
			if (listing != null)
			{
				StorableItemDefinition item = listing.Item;
				if (((item != null) ? ((BaseItemDefinition)item).ID : null) != null)
				{
					obj2 = ((BaseItemDefinition)listing.Item).ID;
					goto IL_0047;
				}
			}
			obj2 = "?";
			goto IL_0047;
			IL_0047:
			string text = (string)obj2;
			return obj + "|" + text;
		}

		public static void ClearListingStockCache()
		{
			LastAppliedStockByListing.Clear();
		}

		private static void ApplyShopSettings(List<ShopListing> listings, ShopInterface shopInterface, ShopListingSettings shopSettings)
		{
			//IL_000b: Unknown result type (might be due to invalid IL or missing references)
			//IL_0112: Unknown result type (might be due to invalid IL or missing references)
			if (!shopSettings.Override)
			{
				return;
			}
			shopInterface.PaymentType = shopSettings.PaymentType;
			foreach (ShopListing listing in listings)
			{
				if (!shopSettings.ItemOverrides.TryGetValue(((BaseItemDefinition)listing.Item).ID, out var value))
				{
					continue;
				}
				int currentStock = listing.CurrentStock;
				int defaultStock = listing.DefaultStock;
				bool limitedStock = listing.LimitedStock;
				listing.LimitedStock = value.Stock >= 0;
				listing.DefaultStock = ((value.Stock >= 0) ? value.Stock : shopSettings.DefaultStock);
				if (value.Stock >= 0)
				{
					int stock = value.Stock;
					string key = ListingStockKey(shopInterface, listing);
					if (currentStock > 0)
					{
						listing.CurrentStock = Mathf.Min(currentStock, stock);
					}
					else if (defaultStock == 0 || !limitedStock)
					{
						listing.CurrentStock = stock;
					}
					else if (!LastAppliedStockByListing.ContainsKey(key))
					{
						listing.CurrentStock = stock;
					}
					else
					{
						listing.CurrentStock = 0;
					}
					LastAppliedStockByListing[key] = listing.CurrentStock;
				}
				listing.OverridePrice = true;
				listing.OverriddenPrice = value.Price;
				listing.RestockRate = value.RestockRate;
			}
		}
	}
	[HarmonyPatch]
	internal static class SupplierPhonePricesReapplyPatches
	{
		private static bool _loggedOnce;

		private static int _hookCount;

		private static bool IsRealMethodForPatch(MethodInfo m)
		{
			if (m.IsSpecialName)
			{
				return false;
			}
			string name = m.Name;
			if (name.StartsWith("set_", StringComparison.Ordinal) || name.StartsWith("get_", StringComparison.Ordinal))
			{
				return false;
			}
			if (name.StartsWith("add_", StringComparison.Ordinal) || name.StartsWith("remove_", StringComparison.Ordinal))
			{
				return false;
			}
			return true;
		}

		private static bool IsFishNetOrNetworkGeneratedMethod(MethodInfo m)
		{
			string name = m.Name;
			if (name.IndexOf("RpcWriter", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			if (name.IndexOf("RpcReader", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			if (name.IndexOf("UserCode_", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			if (name.IndexOf("InvokeUserCode_", StringComparison.OrdinalIgnoreCase) >= 0)
			{
				return true;
			}
			return false;
		}

		[HarmonyPrepare]
		private static bool Prepare()
		{
			try
			{
				_hookCount = TargetMethods().Count();
				return _hookCount > 0;
			}
			catch
			{
				return false;
			}
		}

		private static IEnumerable<MethodBase> SupplierDeaddropHooks()
		{
			MethodInfo[] methods = typeof(Supplier).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (!methodInfo.IsStatic && !(methodInfo.ReturnType != typeof(void)) && methodInfo.GetParameters().Length <= 8 && IsRealMethodForPatch(methodInfo) && !IsFishNetOrNetworkGeneratedMethod(methodInfo) && methodInfo.Name.IndexOf("deaddrop", StringComparison.OrdinalIgnoreCase) >= 0)
				{
					yield return methodInfo;
				}
			}
		}

		private static IEnumerable<MethodBase> SupplierPhoneHooks()
		{
			MethodInfo[] methods = typeof(Supplier).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo i in methods)
			{
				if (!i.IsStatic && !(i.ReturnType != typeof(void)) && i.GetParameters().Length <= 8 && IsRealMethodForPatch(i) && !IsFishNetOrNetworkGeneratedMethod(i))
				{
					string j = i.Name;
					if (j.IndexOf("phone", StringComparison.OrdinalIgnoreCase) >= 0)
					{
						yield return i;
					}
					if (j.IndexOf("onlineshop", StringComparison.OrdinalIgnoreCase) >= 0 && (j.IndexOf("refresh", StringComparison.OrdinalIgnoreCase) >= 0 || j.IndexOf("open", StringComparison.OrdinalIgnoreCase) >= 0 || j.IndexOf("show", StringComparison.OrdinalIgnoreCase) >= 0))
					{
						yield return i;
					}
				}
			}
		}

		private static IEnumerable<MethodBase> PhoneShopOpenHooks()
		{
			MethodInfo[] methods = typeof(PhoneShopInterface).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			foreach (MethodInfo methodInfo in methods)
			{
				if (!methodInfo.IsStatic && !(methodInfo.ReturnType != typeof(void)) && methodInfo.Name.Equals("Open", StringComparison.OrdinalIgnoreCase))
				{
					yield return methodInfo;
				}
			}
		}

		private static IEnumerable<MethodBase> MessageUiPhoneHooks()
		{
			Assembly assembly = typeof(Supplier).Assembly;
			Type[] array;
			try
			{
				array = assembly.GetTypes();
			}
			catch (ReflectionTypeLoadException ex)
			{
				array = ex.Types?.Where((Type t) => t != null).Cast<Type>().ToArray() ?? Array.Empty<Type>();
			}
			Type[] array2 = array;
			foreach (Type type in array2)
			{
				if (type == null || type.Namespace == null || !type.Namespace.Contains("UI.Phone", StringComparison.Ordinal) || (type.Name.IndexOf("Message", StringComparison.OrdinalIgnoreCase) < 0 && type.Name.IndexOf("Conversation", StringComparison.OrdinalIgnoreCase) < 0 && type.Name.IndexOf("DeadDrop", StringComparison.OrdinalIgnoreCase) < 0 && type.Name.IndexOf("Deaddrop", StringComparison.OrdinalIgnoreCase) < 0))
				{
					continue;
				}
				MethodInfo[] methods = type.GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (!methodInfo.IsStatic && !(methodInfo.ReturnType != typeof(void)) && methodInfo.GetParameters().Length <= 8 && IsRealMethodForPatch(methodInfo) && !IsFishNetOrNetworkGeneratedMethod(methodInfo))
					{
						string name = methodInfo.Name;
						if (name.Equals("Open", StringComparison.OrdinalIgnoreCase) || name.Equals("SetOpen", StringComparison.OrdinalIgnoreCase) || name.Equals("Show", StringComparison.OrdinalIgnoreCase) || (name.StartsWith("Open", StringComparison.OrdinalIgnoreCase)