Decompiled source of AutoReorder v1.0.1

AutoReorder.dll

Decompiled a day ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Text;
using AutoReorder;
using HarmonyLib;
using MelonLoader;
using Microsoft.CodeAnalysis;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(Core), "AutoReorder", "1.0.1", "HazDS", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("AutoReorder")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+5bb5186c319c06a3dc0d8474ec24c49e8b7987a8")]
[assembly: AssemblyProduct("AutoReorder")]
[assembly: AssemblyTitle("AutoReorder")]
[assembly: AssemblyVersion("1.0.0.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.Module, AllowMultiple = false, Inherited = false)]
	internal sealed class RefSafetyRulesAttribute : Attribute
	{
		public readonly int Version;

		public RefSafetyRulesAttribute(int P_0)
		{
			Version = P_0;
		}
	}
}
namespace AutoReorder
{
	public class Core : MelonMod
	{
		[CompilerGenerated]
		private sealed class <DoAutoReorder>d__28 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public AutoReorderEntry entry;

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

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

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

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

			private bool MoveNext()
			{
				//IL_0026: Unknown result type (might be due to invalid IL or missing references)
				//IL_0030: Expected O, but got Unknown
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<>2__current = (object)new WaitForSeconds(1f);
					<>1__state = 1;
					return true;
				case 1:
					<>1__state = -1;
					ExecuteAutoReorder(entry);
					entry.ReorderPending = false;
					return false;
				}
			}

			bool IEnumerator.MoveNext()
			{
				//ILSpy generated this explicit interface implementation from .override directive in MoveNext
				return this.MoveNext();
			}

			[DebuggerHidden]
			void IEnumerator.Reset()
			{
				throw new NotSupportedException();
			}
		}

		private bool _initialized;

		private static Type _deliveryManagerType;

		private static Type _deliveryAppType;

		private static Type _deliveryReceiptDisplayType;

		private static Type _loadManagerType;

		private static Type _saveManagerType;

		private static MethodInfo _getActiveShopDelivery;

		private static bool _saveHooksWired;

		private const string PersistFileName = "AutoReorder.json";

		public static readonly Dictionary<string, AutoReorderEntry> ActiveAutoReorders = new Dictionary<string, AutoReorderEntry>();

		private static readonly Dictionary<object, GameObject> _autoReorderButtons = new Dictionary<object, GameObject>();

		public static Core Instance { get; private set; }

		public override void OnInitializeMelon()
		{
			Instance = this;
			CacheTypes();
			ApplyPatches();
			((MelonBase)this).LoggerInstance.Msg("AutoReorder initialized!");
		}

		private void CacheTypes()
		{
			_deliveryManagerType = CrossCompat.FindType("ScheduleOne.Delivery.DeliveryManager");
			_deliveryAppType = CrossCompat.FindType("ScheduleOne.UI.Phone.Delivery.DeliveryApp");
			_deliveryReceiptDisplayType = CrossCompat.FindType("ScheduleOne.UI.Phone.Delivery.DeliveryReceiptDisplay");
			_loadManagerType = CrossCompat.FindType("ScheduleOne.Persistence.LoadManager");
			_saveManagerType = CrossCompat.FindType("ScheduleOne.Persistence.SaveManager");
			if (_deliveryManagerType == null)
			{
				((MelonBase)this).LoggerInstance.Error("Could not find DeliveryManager type");
			}
			if (_deliveryAppType == null)
			{
				((MelonBase)this).LoggerInstance.Error("Could not find DeliveryApp type");
			}
			if (_deliveryReceiptDisplayType == null)
			{
				((MelonBase)this).LoggerInstance.Error("Could not find DeliveryReceiptDisplay type");
			}
			if (_loadManagerType == null)
			{
				((MelonBase)this).LoggerInstance.Error("Could not find LoadManager type");
			}
			if (_saveManagerType == null)
			{
				((MelonBase)this).LoggerInstance.Error("Could not find SaveManager type");
			}
		}

		private void ApplyPatches()
		{
			//IL_0048: Unknown result type (might be due to invalid IL or missing references)
			//IL_0055: Expected O, but got Unknown
			if (_deliveryReceiptDisplayType != null)
			{
				MethodInfo methodInfo = CrossCompat.FindMethod(_deliveryReceiptDisplayType, "Set", 3);
				if (methodInfo != null)
				{
					((MelonBase)this).HarmonyInstance.Patch((MethodBase)methodInfo, (HarmonyMethod)null, new HarmonyMethod(typeof(Core), "ReceiptDisplay_Set_Postfix", (Type[])null), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null);
					((MelonBase)this).LoggerInstance.Msg("Patched DeliveryReceiptDisplay.Set");
				}
				else
				{
					((MelonBase)this).LoggerInstance.Error("Could not find DeliveryReceiptDisplay.Set method");
				}
			}
			if (_deliveryManagerType != null)
			{
				_getActiveShopDelivery = CrossCompat.FindMethod(_deliveryManagerType, "GetActiveShopDelivery", 1);
				if (_getActiveShopDelivery == null)
				{
					((MelonBase)this).LoggerInstance.Warning("Could not find GetActiveShopDelivery method");
				}
			}
		}

		public override void OnSceneWasLoaded(int buildIndex, string sceneName)
		{
			if (sceneName == "Menu")
			{
				_initialized = false;
				ActiveAutoReorders.Clear();
				_autoReorderButtons.Clear();
			}
		}

		public override void OnSceneWasInitialized(int buildIndex, string sceneName)
		{
			if (sceneName == "Main" && !_initialized)
			{
				_initialized = true;
				WireSaveHooks();
			}
		}

		private static void WireSaveHooks()
		{
			if (_saveHooksWired)
			{
				return;
			}
			try
			{
				object singletonInstance = GetSingletonInstance(_loadManagerType);
				object singletonInstance2 = GetSingletonInstance(_saveManagerType);
				if (singletonInstance != null)
				{
					object memberValue = CrossCompat.GetMemberValue(singletonInstance, "onLoadComplete");
					if (memberValue != null)
					{
						AddUnityEventListener(memberValue, RestoreState);
						Melon<Core>.Logger.Msg("Hooked LoadManager.onLoadComplete");
					}
					else
					{
						Melon<Core>.Logger.Warning("LoadManager.onLoadComplete not found");
					}
				}
				if (singletonInstance2 != null)
				{
					object memberValue2 = CrossCompat.GetMemberValue(singletonInstance2, "onSaveComplete");
					if (memberValue2 != null)
					{
						AddUnityEventListener(memberValue2, SaveState);
						Melon<Core>.Logger.Msg("Hooked SaveManager.onSaveComplete");
					}
					else
					{
						Melon<Core>.Logger.Warning("SaveManager.onSaveComplete not found");
					}
				}
				_saveHooksWired = true;
			}
			catch (Exception ex)
			{
				Melon<Core>.Logger.Error("WireSaveHooks failed: " + ex.Message);
				Melon<Core>.Logger.Error("Stack trace: " + ex.StackTrace);
			}
		}

		private static string GetLoadedGameFolderPath()
		{
			object singletonInstance = GetSingletonInstance(_loadManagerType);
			if (singletonInstance == null)
			{
				return null;
			}
			return CrossCompat.GetMemberValue(singletonInstance, "LoadedGameFolderPath") as string;
		}

		private static void SaveState()
		{
			try
			{
				string loadedGameFolderPath = GetLoadedGameFolderPath();
				if (string.IsNullOrEmpty(loadedGameFolderPath))
				{
					return;
				}
				StringBuilder stringBuilder = new StringBuilder();
				stringBuilder.Append("{\"v\":1,\"ids\":[");
				bool flag = true;
				foreach (KeyValuePair<string, AutoReorderEntry> activeAutoReorder in ActiveAutoReorders)
				{
					if (!flag)
					{
						stringBuilder.Append(',');
					}
					flag = false;
					stringBuilder.Append('"').Append(JsonEscape(activeAutoReorder.Key)).Append('"');
				}
				stringBuilder.Append("]}");
				string text = Path.Combine(loadedGameFolderPath, "AutoReorder.json");
				File.WriteAllText(text, stringBuilder.ToString());
				Melon<Core>.Logger.Msg($"Saved {ActiveAutoReorders.Count} auto-reorder(s) to {text}");
			}
			catch (Exception ex)
			{
				Melon<Core>.Logger.Error("SaveState failed: " + ex.Message);
				Melon<Core>.Logger.Error("Stack trace: " + ex.StackTrace);
			}
		}

		private static void RestoreState()
		{
			try
			{
				string loadedGameFolderPath = GetLoadedGameFolderPath();
				if (string.IsNullOrEmpty(loadedGameFolderPath))
				{
					return;
				}
				string text = Path.Combine(loadedGameFolderPath, "AutoReorder.json");
				if (!File.Exists(text))
				{
					return;
				}
				string json = File.ReadAllText(text);
				List<string> list = ParseIdList(json);
				if (list.Count == 0)
				{
					return;
				}
				object networkSingletonInstance = GetNetworkSingletonInstance(_deliveryManagerType);
				if (networkSingletonInstance == null)
				{
					Melon<Core>.Logger.Warning("DeliveryManager unavailable — cannot restore auto-reorders");
					return;
				}
				object memberValue = CrossCompat.GetMemberValue(networkSingletonInstance, "DisplayedDeliveryHistory");
				if (!(memberValue is IEnumerable enumerable))
				{
					Melon<Core>.Logger.Warning("DisplayedDeliveryHistory is not enumerable");
					return;
				}
				Dictionary<string, object> dictionary = new Dictionary<string, object>();
				foreach (object item in enumerable)
				{
					if (item != null)
					{
						string text2 = CrossCompat.GetMemberValue(item, "DeliveryID") as string;
						if (!string.IsNullOrEmpty(text2))
						{
							dictionary[text2] = item;
						}
					}
				}
				object playerSingletonInstance = GetPlayerSingletonInstance(_deliveryAppType);
				int num = 0;
				foreach (string item2 in list)
				{
					if (dictionary.TryGetValue(item2, out var value))
					{
						string text3 = CrossCompat.GetMemberValue(value, "StoreName") as string;
						bool hadActiveDelivery = playerSingletonInstance != null && !string.IsNullOrEmpty(text3) && ShopHasActiveDelivery(playerSingletonInstance, text3);
						ActiveAutoReorders[item2] = new AutoReorderEntry
						{
							Receipt = value,
							ShopName = text3,
							DeliveryId = item2,
							HadActiveDelivery = hadActiveDelivery,
							ReorderPending = false
						};
						num++;
					}
				}
				Melon<Core>.Logger.Msg($"Restored {num}/{list.Count} auto-reorder(s) from {text}");
			}
			catch (Exception ex)
			{
				Melon<Core>.Logger.Error("RestoreState failed: " + ex.Message);
				Melon<Core>.Logger.Error("Stack trace: " + ex.StackTrace);
			}
		}

		private static string JsonEscape(string s)
		{
			if (string.IsNullOrEmpty(s))
			{
				return string.Empty;
			}
			StringBuilder stringBuilder = new StringBuilder(s.Length);
			foreach (char c in s)
			{
				switch (c)
				{
				case '"':
					stringBuilder.Append("\\\"");
					continue;
				case '\\':
					stringBuilder.Append("\\\\");
					continue;
				case '\n':
					stringBuilder.Append("\\n");
					continue;
				case '\r':
					stringBuilder.Append("\\r");
					continue;
				case '\t':
					stringBuilder.Append("\\t");
					continue;
				}
				if (c < ' ')
				{
					stringBuilder.AppendFormat("\\u{0:x4}", (int)c);
				}
				else
				{
					stringBuilder.Append(c);
				}
			}
			return stringBuilder.ToString();
		}

		private static List<string> ParseIdList(string json)
		{
			List<string> list = new List<string>();
			if (string.IsNullOrEmpty(json))
			{
				return list;
			}
			int num = json.IndexOf("\"ids\"", StringComparison.Ordinal);
			if (num < 0)
			{
				return list;
			}
			int num2 = json.IndexOf('[', num);
			if (num2 < 0)
			{
				return list;
			}
			int num3 = json.IndexOf(']', num2);
			if (num3 < 0)
			{
				return list;
			}
			int num4 = num2 + 1;
			while (num4 < num3)
			{
				if (json[num4] == '"')
				{
					int num5 = num4 + 1;
					StringBuilder stringBuilder = new StringBuilder();
					num4 = num5;
					while (num4 < num3 && json[num4] != '"')
					{
						if (json[num4] == '\\' && num4 + 1 < num3)
						{
							char c = json[num4 + 1];
							switch (c)
							{
							case '"':
								stringBuilder.Append('"');
								break;
							case '\\':
								stringBuilder.Append('\\');
								break;
							case 'n':
								stringBuilder.Append('\n');
								break;
							case 'r':
								stringBuilder.Append('\r');
								break;
							case 't':
								stringBuilder.Append('\t');
								break;
							default:
								stringBuilder.Append(c);
								break;
							}
							num4 += 2;
						}
						else
						{
							stringBuilder.Append(json[num4]);
							num4++;
						}
					}
					list.Add(stringBuilder.ToString());
					num4++;
				}
				else
				{
					num4++;
				}
			}
			return list;
		}

		public override void OnUpdate()
		{
			if (!_initialized || ActiveAutoReorders.Count == 0 || Time.frameCount % 60 != 0)
			{
				return;
			}
			try
			{
				object networkSingletonInstance = GetNetworkSingletonInstance(_deliveryManagerType);
				if (networkSingletonInstance == null)
				{
					return;
				}
				object playerSingletonInstance = GetPlayerSingletonInstance(_deliveryAppType);
				if (playerSingletonInstance == null)
				{
					return;
				}
				List<KeyValuePair<string, AutoReorderEntry>> list = new List<KeyValuePair<string, AutoReorderEntry>>(ActiveAutoReorders);
				foreach (KeyValuePair<string, AutoReorderEntry> item in list)
				{
					AutoReorderEntry value = item.Value;
					if (ShopHasActiveDelivery(playerSingletonInstance, value.ShopName))
					{
						value.HadActiveDelivery = true;
					}
					else if (value.HadActiveDelivery && !value.ReorderPending)
					{
						value.HadActiveDelivery = false;
						value.ReorderPending = true;
						((MelonBase)this).LoggerInstance.Msg("Detected delivery completion for " + value.ShopName + ", triggering auto-reorder...");
						MelonCoroutines.Start(DoAutoReorder(value));
					}
				}
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Error("OnUpdate poll failed: " + ex.Message);
			}
		}

		private static bool ShopHasActiveDelivery(object deliveryApp, string shopName)
		{
			MethodInfo methodInfo = CrossCompat.FindMethod(_deliveryAppType, "GetShop", 1);
			if (methodInfo == null)
			{
				return false;
			}
			object obj = methodInfo.Invoke(deliveryApp, new object[1] { shopName });
			if (obj == null)
			{
				return false;
			}
			object networkSingletonInstance = GetNetworkSingletonInstance(_deliveryManagerType);
			if (networkSingletonInstance == null || _getActiveShopDelivery == null)
			{
				return false;
			}
			object obj2 = _getActiveShopDelivery.Invoke(networkSingletonInstance, new object[1] { obj });
			return obj2 != null;
		}

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

		private static void ExecuteAutoReorder(AutoReorderEntry entry)
		{
			try
			{
				object playerSingletonInstance = GetPlayerSingletonInstance(_deliveryAppType);
				if (playerSingletonInstance == null)
				{
					Melon<Core>.Logger.Warning("DeliveryApp not found, cannot auto-reorder.");
					return;
				}
				MethodInfo methodInfo = CrossCompat.FindMethod(_deliveryAppType, "Reorder", 1);
				if (methodInfo != null)
				{
					methodInfo.Invoke(playerSingletonInstance, new object[1] { entry.Receipt });
					Melon<Core>.Logger.Msg("Auto-reorder placed for " + entry.ShopName + "!");
				}
			}
			catch (Exception ex)
			{
				Melon<Core>.Logger.Error("ExecuteAutoReorder failed: " + ex.Message);
				Melon<Core>.Logger.Error("Stack trace: " + ex.StackTrace);
			}
		}

		public static void ReceiptDisplay_Set_Postfix(object __instance)
		{
			try
			{
				object obj = CrossCompat.GetMemberValue(__instance, "Receipt") ?? CrossCompat.GetMemberValue(__instance, "_receipt");
				if (obj == null)
				{
					return;
				}
				string text = CrossCompat.GetMemberValue(obj, "DeliveryID") as string;
				if (string.IsNullOrEmpty(text))
				{
					return;
				}
				if (!_autoReorderButtons.TryGetValue(__instance, out var value) || (Object)(object)value == (Object)null)
				{
					value = CreateAutoReorderButton(__instance);
					if ((Object)(object)value == (Object)null)
					{
						return;
					}
					_autoReorderButtons[__instance] = value;
				}
				bool isEnabled = ActiveAutoReorders.ContainsKey(text);
				UpdateButtonVisual(value, isEnabled);
				Button comp = CrossCompat.GetComp<Button>(value);
				if (!((Object)(object)comp == (Object)null))
				{
					((UnityEventBase)comp.onClick).RemoveAllListeners();
					object capturedReceipt = obj;
					string capturedId = text;
					GameObject capturedBtnObj = value;
					AddButtonListener(comp, delegate
					{
						bool isEnabled2 = ToggleAutoReorder(capturedReceipt, capturedId);
						UpdateButtonVisual(capturedBtnObj, isEnabled2);
						RefreshAllButtons();
					});
				}
			}
			catch (Exception ex)
			{
				Melon<Core>.Logger.Error("ReceiptDisplay_Set_Postfix failed: " + ex.Message);
				Melon<Core>.Logger.Error("Stack trace: " + ex.StackTrace);
			}
		}

		private static GameObject CreateAutoReorderButton(object displayInstance)
		{
			//IL_00a4: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ab: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00d5: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e7: Unknown result type (might be due to invalid IL or missing references)
			//IL_00f1: Unknown result type (might be due to invalid IL or missing references)
			object obj = CrossCompat.GetMemberValue(displayInstance, "ReorderButton") ?? CrossCompat.GetMemberValue(displayInstance, "_ReorderButton");
			if (obj == null)
			{
				return null;
			}
			object memberValue = CrossCompat.GetMemberValue(obj, "gameObject");
			GameObject val = (GameObject)((memberValue is GameObject) ? memberValue : null);
			if ((Object)(object)val == (Object)null)
			{
				return null;
			}
			Transform parent = val.transform.parent;
			GameObject val2 = Object.Instantiate<GameObject>(val, parent);
			((Object)val2).name = "AutoReorderButton";
			RectTransform comp = CrossCompat.GetComp<RectTransform>(val);
			RectTransform comp2 = CrossCompat.GetComp<RectTransform>(val2);
			if ((Object)(object)comp != (Object)null && (Object)(object)comp2 != (Object)null)
			{
				comp2.anchoredPosition = comp.anchoredPosition + new Vector2(0f - comp.sizeDelta.x - 8f, 0f);
				comp2.sizeDelta = new Vector2(comp.sizeDelta.x * 0.85f, comp.sizeDelta.y);
			}
			bool flag = false;
			for (int i = 0; i < val2.transform.childCount; i++)
			{
				Transform child = val2.transform.GetChild(i);
				Text comp3 = CrossCompat.GetComp<Text>(((Component)child).gameObject);
				if ((Object)(object)comp3 != (Object)null)
				{
					if (!flag)
					{
						comp3.text = "Auto";
						comp3.fontSize = Mathf.Max(comp3.fontSize - 2, 10);
						flag = true;
					}
					else
					{
						((Component)child).gameObject.SetActive(false);
					}
				}
			}
			try
			{
				Type type = CrossCompat.FindType("ScheduleOne.UI.Tooltips.Tooltip");
				if (type != null)
				{
					if (CrossCompat._goGetComponentGeneric == null)
					{
						MethodInfo[] methods = typeof(GameObject).GetMethods(BindingFlags.Instance | BindingFlags.Public);
						foreach (MethodInfo methodInfo in methods)
						{
							if (methodInfo.Name == "GetComponent" && methodInfo.IsGenericMethod && methodInfo.GetParameters().Length == 0)
							{
								CrossCompat._goGetComponentGeneric = methodInfo;
								break;
							}
						}
					}
					if (CrossCompat._goGetComponentGeneric != null)
					{
						MethodInfo methodInfo2 = CrossCompat._goGetComponentGeneric.MakeGenericMethod(type);
						object obj2 = methodInfo2.Invoke(val2, null);
						Component val3 = (Component)((obj2 is Component) ? obj2 : null);
						if (val3 != null)
						{
							Object.Destroy((Object)(object)val3);
						}
					}
				}
			}
			catch
			{
			}
			Button comp4 = CrossCompat.GetComp<Button>(val2);
			if ((Object)(object)comp4 == (Object)null)
			{
				return null;
			}
			((UnityEventBase)comp4.onClick).RemoveAllListeners();
			((Selectable)comp4).interactable = true;
			return val2;
		}

		private static void AddButtonListener(Button button, Action callback)
		{
			if (!((Object)(object)button == (Object)null))
			{
				AddUnityEventListener(button.onClick, callback);
			}
		}

		private static void AddUnityEventListener(object unityEvent, Action callback)
		{
			if (unityEvent == null)
			{
				return;
			}
			MethodInfo methodInfo = null;
			MethodInfo[] methods = unityEvent.GetType().GetMethods(BindingFlags.Instance | BindingFlags.Public);
			foreach (MethodInfo methodInfo2 in methods)
			{
				if (methodInfo2.Name == "AddListener" && !methodInfo2.IsGenericMethod && methodInfo2.GetParameters().Length == 1)
				{
					methodInfo = methodInfo2;
					break;
				}
			}
			if (methodInfo == null)
			{
				return;
			}
			Type parameterType = methodInfo.GetParameters()[0].ParameterType;
			ConstructorInfo[] constructors = parameterType.GetConstructors();
			foreach (ConstructorInfo constructorInfo in constructors)
			{
				ParameterInfo[] parameters = constructorInfo.GetParameters();
				if (parameters.Length == 1 && parameters[0].ParameterType == typeof(Action))
				{
					object obj = constructorInfo.Invoke(new object[1] { callback });
					methodInfo.Invoke(unityEvent, new object[1] { obj });
					return;
				}
			}
			MethodInfo[] methods2 = parameterType.GetMethods(BindingFlags.Static | BindingFlags.Public);
			foreach (MethodInfo methodInfo3 in methods2)
			{
				if ((methodInfo3.Name == "op_Implicit" || methodInfo3.Name == "op_Explicit") && methodInfo3.GetParameters().Length == 1 && methodInfo3.GetParameters()[0].ParameterType == typeof(Action))
				{
					object obj2 = methodInfo3.Invoke(null, new object[1] { callback });
					methodInfo.Invoke(unityEvent, new object[1] { obj2 });
					return;
				}
			}
			if (typeof(Delegate).IsAssignableFrom(parameterType))
			{
				Delegate @delegate = Delegate.CreateDelegate(parameterType, callback.Target, callback.Method);
				methodInfo.Invoke(unityEvent, new object[1] { @delegate });
			}
			else
			{
				Melon<Core>.Logger.Error("AddUnityEventListener: Could not create delegate for type " + parameterType.FullName);
			}
		}

		private static void UpdateButtonVisual(GameObject btnObj, bool isEnabled)
		{
			//IL_0028: Unknown result type (might be due to invalid IL or missing references)
			//IL_002d: Unknown result type (might be due to invalid IL or missing references)
			//IL_0063: Unknown result type (might be due to invalid IL or missing references)
			//IL_0048: 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_0087: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e1: Unknown result type (might be due to invalid IL or missing references)
			//IL_00c6: Unknown result type (might be due to invalid IL or missing references)
			//IL_00ed: Unknown result type (might be due to invalid IL or missing references)
			if (!((Object)(object)btnObj == (Object)null))
			{
				Button comp = CrossCompat.GetComp<Button>(btnObj);
				if ((Object)(object)comp != (Object)null)
				{
					ColorBlock colors = ((Selectable)comp).colors;
					((ColorBlock)(ref colors)).normalColor = (isEnabled ? new Color(0.2f, 0.75f, 0.2f, 1f) : new Color(0.6f, 0.6f, 0.6f, 1f));
					((ColorBlock)(ref colors)).highlightedColor = (isEnabled ? new Color(0.15f, 0.65f, 0.15f, 1f) : new Color(0.5f, 0.5f, 0.5f, 1f));
					((ColorBlock)(ref colors)).pressedColor = (isEnabled ? new Color(0.1f, 0.55f, 0.1f, 1f) : new Color(0.4f, 0.4f, 0.4f, 1f));
					((Selectable)comp).colors = colors;
				}
				Text compInChildren = CrossCompat.GetCompInChildren<Text>(btnObj);
				if ((Object)(object)compInChildren != (Object)null)
				{
					compInChildren.text = (isEnabled ? "Auto ON" : "Auto");
				}
			}
		}

		private static void RefreshAllButtons()
		{
			foreach (KeyValuePair<object, GameObject> autoReorderButton in _autoReorderButtons)
			{
				if (autoReorderButton.Key != null && !((Object)(object)autoReorderButton.Value == (Object)null))
				{
					object obj = CrossCompat.GetMemberValue(autoReorderButton.Key, "Receipt") ?? CrossCompat.GetMemberValue(autoReorderButton.Key, "_receipt");
					if (obj != null)
					{
						bool isEnabled = CrossCompat.GetMemberValue(obj, "DeliveryID") is string key && ActiveAutoReorders.ContainsKey(key);
						UpdateButtonVisual(autoReorderButton.Value, isEnabled);
					}
				}
			}
		}

		private static bool ToggleAutoReorder(object receipt, string deliveryId)
		{
			if (ActiveAutoReorders.ContainsKey(deliveryId))
			{
				RemoveAutoReorder(deliveryId);
				return false;
			}
			string text = CrossCompat.GetMemberValue(receipt, "StoreName") as string;
			string text2 = null;
			foreach (KeyValuePair<string, AutoReorderEntry> activeAutoReorder in ActiveAutoReorders)
			{
				if (activeAutoReorder.Value.ShopName == text)
				{
					text2 = activeAutoReorder.Key;
					break;
				}
			}
			if (text2 != null)
			{
				RemoveAutoReorder(text2);
			}
			object playerSingletonInstance = GetPlayerSingletonInstance(_deliveryAppType);
			bool flag = playerSingletonInstance != null && ShopHasActiveDelivery(playerSingletonInstance, text);
			ActiveAutoReorders[deliveryId] = new AutoReorderEntry
			{
				Receipt = receipt,
				ShopName = text,
				DeliveryId = deliveryId,
				HadActiveDelivery = flag,
				ReorderPending = false
			};
			Melon<Core>.Logger.Msg("Auto-reorder enabled for " + text + " (ID: " + deliveryId + ")");
			if (!flag)
			{
				AutoReorderEntry autoReorderEntry = ActiveAutoReorders[deliveryId];
				autoReorderEntry.ReorderPending = true;
				MelonCoroutines.Start(DoAutoReorder(autoReorderEntry));
			}
			return true;
		}

		private static void RemoveAutoReorder(string deliveryId)
		{
			if (ActiveAutoReorders.TryGetValue(deliveryId, out var value))
			{
				ActiveAutoReorders.Remove(deliveryId);
				Melon<Core>.Logger.Msg("Auto-reorder disabled for " + value.ShopName + " (ID: " + deliveryId + ")");
			}
		}

		private static object GetNetworkSingletonInstance(Type gameType)
		{
			if (gameType == null)
			{
				return null;
			}
			Type type = CrossCompat.FindType("ScheduleOne.DevUtilities.NetworkSingleton`1");
			if (type == null)
			{
				return null;
			}
			return CrossCompat.GetStaticMemberValue(type.MakeGenericType(gameType), "Instance");
		}

		private static object GetPlayerSingletonInstance(Type gameType)
		{
			if (gameType == null)
			{
				return null;
			}
			Type type = CrossCompat.FindType("ScheduleOne.DevUtilities.PlayerSingleton`1");
			if (type == null)
			{
				return null;
			}
			return CrossCompat.GetStaticMemberValue(type.MakeGenericType(gameType), "Instance");
		}

		private static object GetSingletonInstance(Type gameType)
		{
			if (gameType == null)
			{
				return null;
			}
			Type type = CrossCompat.FindType("ScheduleOne.DevUtilities.Singleton`1");
			if (type == null)
			{
				return null;
			}
			return CrossCompat.GetStaticMemberValue(type.MakeGenericType(gameType), "Instance");
		}
	}
	public class AutoReorderEntry
	{
		public object Receipt;

		public string ShopName;

		public string DeliveryId;

		public bool HadActiveDelivery;

		public bool ReorderPending;
	}
	public static class CrossCompat
	{
		internal static MethodInfo _goGetComponentGeneric;

		private static MethodInfo _goGetComponentInChildrenGeneric;

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

		private const BindingFlags AllStatic = BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;

		public static Type FindType(string fullName)
		{
			string name = (fullName.StartsWith("ScheduleOne") ? ("Il2Cpp" + fullName) : fullName);
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				Type type = assembly.GetType(fullName) ?? assembly.GetType(name);
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}

		public static object GetMemberValue(object obj, string name)
		{
			if (obj == null)
			{
				return null;
			}
			Type type = obj.GetType();
			PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null)
			{
				return property.GetValue(obj);
			}
			FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				return field.GetValue(obj);
			}
			return null;
		}

		public static void SetMemberValue(object obj, string name, object value)
		{
			if (obj == null)
			{
				return;
			}
			Type type = obj.GetType();
			PropertyInfo property = type.GetProperty(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null && property.CanWrite)
			{
				property.SetValue(obj, value);
				return;
			}
			FieldInfo field = type.GetField(name, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				field.SetValue(obj, value);
			}
		}

		public static object GetStaticMemberValue(Type type, string name)
		{
			if (type == null)
			{
				return null;
			}
			PropertyInfo property = type.GetProperty(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (property != null)
			{
				return property.GetValue(null);
			}
			FieldInfo field = type.GetField(name, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (field != null)
			{
				return field.GetValue(null);
			}
			return null;
		}

		public static object InvokeMethod(object obj, string methodName, params object[] args)
		{
			if (obj == null)
			{
				return null;
			}
			Type type = obj.GetType();
			MethodInfo method = type.GetMethod(methodName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
			if (method != null)
			{
				return method.Invoke(obj, args);
			}
			return null;
		}

		public static object InvokeStaticMethod(Type type, string methodName, params object[] args)
		{
			if (type == null)
			{
				return null;
			}
			MethodInfo method = type.GetMethod(methodName, BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
			if (method != null)
			{
				return method.Invoke(null, args);
			}
			return null;
		}

		public static MethodInfo FindMethod(Type type, string name, int paramCount, BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)
		{
			if (type == null)
			{
				return null;
			}
			MethodInfo[] methods = type.GetMethods(flags);
			foreach (MethodInfo methodInfo in methods)
			{
				if (methodInfo.Name == name && !methodInfo.IsGenericMethod && methodInfo.GetParameters().Length == paramCount)
				{
					return methodInfo;
				}
			}
			return null;
		}

		public static T GetComp<T>(GameObject go) where T : class
		{
			if ((Object)(object)go == (Object)null)
			{
				return null;
			}
			if (_goGetComponentGeneric == null)
			{
				MethodInfo[] methods = typeof(GameObject).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (methodInfo.Name == "GetComponent" && methodInfo.IsGenericMethod && methodInfo.GetParameters().Length == 0)
					{
						_goGetComponentGeneric = methodInfo;
						break;
					}
				}
			}
			if (_goGetComponentGeneric != null)
			{
				try
				{
					MethodInfo methodInfo2 = _goGetComponentGeneric.MakeGenericMethod(typeof(T));
					return methodInfo2.Invoke(go, null) as T;
				}
				catch
				{
				}
			}
			return null;
		}

		public static T GetCompInChildren<T>(GameObject go) where T : class
		{
			if ((Object)(object)go == (Object)null)
			{
				return null;
			}
			if (_goGetComponentInChildrenGeneric == null)
			{
				MethodInfo[] methods = typeof(GameObject).GetMethods(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
				foreach (MethodInfo methodInfo in methods)
				{
					if (methodInfo.Name == "GetComponentInChildren" && methodInfo.IsGenericMethod && methodInfo.GetParameters().Length == 0)
					{
						_goGetComponentInChildrenGeneric = methodInfo;
						break;
					}
				}
			}
			if (_goGetComponentInChildrenGeneric != null)
			{
				try
				{
					MethodInfo methodInfo2 = _goGetComponentInChildrenGeneric.MakeGenericMethod(typeof(T));
					return methodInfo2.Invoke(go, null) as T;
				}
				catch
				{
				}
			}
			return null;
		}
	}
}