Decompiled source of CustomStack v1.1.4

CustomStack-IL2CPP.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using CustomStack;
using CustomStack.Helpers;
using HarmonyLib;
using Il2CppFishNet;
using Il2CppInterop.Runtime;
using Il2CppInterop.Runtime.InteropTypes;
using Il2CppInterop.Runtime.InteropTypes.Arrays;
using Il2CppScheduleOne;
using Il2CppScheduleOne.DevUtilities;
using Il2CppScheduleOne.ItemFramework;
using Il2CppScheduleOne.Money;
using Il2CppScheduleOne.PlayerScripts;
using Il2CppScheduleOne.UI;
using Il2CppScheduleOne.UI.Items;
using Il2CppSystem;
using Il2CppSystem.Collections.Generic;
using Il2CppTMPro;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(global::CustomStack.CustomStack), "CustomStack", "1.1.4", "k073l", null)]
[assembly: MelonColor(1, 255, 0, 0)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("CustomStack-IL2CPP")]
[assembly: AssemblyConfiguration("Release IL2CPP")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+835b10c98b554d9da32dfb1db1a00985d176c9c5")]
[assembly: AssemblyProduct("CustomStack-IL2CPP")]
[assembly: AssemblyTitle("CustomStack-IL2CPP")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.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.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = 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 CustomStack
{
	public static class BuildInfo
	{
		public const string Name = "CustomStack";

		public const string Description = "Custom stack limits, per item";

		public const string Author = "k073l";

		public const string Version = "1.1.4";
	}
	public class CustomStack : MelonMod
	{
		private static Instance _logger;

		private static MelonPreferences_Category _category;

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

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

		private static bool _populatedDefaultLimits = false;

		public override void OnInitializeMelon()
		{
			_logger = ((MelonBase)this).LoggerInstance;
			_logger.Msg("CustomStack initialized.");
			_category = MelonPreferences.CreateCategory("CustomStack");
			_category.SetFilePath(Path.Combine(MelonEnvironment.UserDataDirectory, "CustomStack.cfg"));
		}

		public override void OnSceneWasInitialized(int buildIndex, string sceneName)
		{
			if (sceneName == "Menu")
			{
				LoadAllItems();
			}
			_logger.Debug("Scene loaded: " + sceneName);
		}

		private static void LoadAllItems()
		{
			if (_populatedDefaultLimits)
			{
				_logger.Msg("Item limits already set, skipping.");
				return;
			}
			_logger.Msg("Loading item stack limits...");
			IEnumerable<ItemRegister> enumerable = Singleton<Registry>.Instance.ItemRegistry.AsEnumerable<ItemRegister>();
			_category.LoadFromFile(false);
			foreach (ItemRegister item in enumerable)
			{
				string iD = item.ID;
				int stackLimit = item.Definition.StackLimit;
				if (!Entries.ContainsKey(iD))
				{
					MelonPreferences_Entry<int> value = _category.CreateEntry<int>(iD, stackLimit, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
					Entries[iD] = value;
				}
				if (!_populatedDefaultLimits && !_defaultLimits.ContainsKey(iD))
				{
					_defaultLimits[iD] = stackLimit;
				}
				MelonPreferences_Entry<int> val = Entries[iD];
				int value2 = val.Value;
				if (iD == "cash")
				{
					if (value2 == _defaultLimits[iD])
					{
						_logger.Msg("Cash stack limit not configured, forcing runtime limit to 1k (config not changed).");
						item.Definition.StackLimit = 1000;
						continue;
					}
					item.Definition.StackLimit = value2;
					if (value2 != _defaultLimits[iD])
					{
						_logger.Msg($"cash limit overridden by user: {_defaultLimits[iD]} → {value2}");
					}
				}
				else
				{
					item.Definition.StackLimit = value2;
					if (value2 != _defaultLimits[iD])
					{
						_logger.Msg($"{iD} limit overridden: {_defaultLimits[iD]} → {value2}");
					}
				}
			}
			_populatedDefaultLimits = true;
		}
	}
}
namespace CustomStack.Patches
{
	[HarmonyPatch(typeof(ItemUIManager))]
	public static class CashPatches
	{
		private static int CashItemLimit;

		private static Instance Logger;

		[HarmonyPatch("StartDragCash")]
		[HarmonyPrefix]
		private static bool StartDragCash(ItemUIManager __instance)
		{
			//IL_00d0: 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_00e4: Unknown result type (might be due to invalid IL or missing references)
			Logger.Debug("StartDragCash: top");
			ItemInstance itemInstance = __instance.draggedSlot.assignedSlot.ItemInstance;
			if (!Utils.Is<CashInstance>((object)itemInstance, out CashInstance result))
			{
				Logger.Debug("StartDragCash: cashInstance is null");
			}
			Logger.Debug("StartDragCash: got cashInstance");
			__instance.draggedCashAmount = Mathf.Min(result.Balance, (float)CashItemLimit);
			__instance.draggedAmount = 1;
			Logger.Debug("Set draggedCashAmount and draggedAmount");
			if (GameInput.GetButtonDown((ButtonCode)1))
			{
				Logger.Debug("StartDragCash: secondary click");
				__instance.draggedAmount = 1;
				__instance.draggedCashAmount = Mathf.Min(result.Balance, Mathf.Floor((float)CashItemLimit / 10f));
				__instance.mouseOffset += new Vector2(-10f, -15f);
				__instance.customDragAmount = true;
			}
			Logger.Debug("StartDragCash: draggedAmount check");
			if (__instance.draggedCashAmount <= 0f)
			{
				Logger.Debug("StartDragCash: no cash to drag");
				__instance.draggedSlot = null;
			}
			else if (GameInput.GetButton((ButtonCode)23) && __instance.QuickMoveEnabled)
			{
				Logger.Debug("StartDragCash: quickmove");
				List<ItemSlot> list = Il2CppListExtensions.ConvertToList<ItemSlot>(__instance.GetQuickMoveSlots(__instance.draggedSlot.assignedSlot));
				if (list.Count > 0)
				{
					Logger.Debug("StartDragCash: quickmove slots found");
					Debug.Log(Object.op_Implicit("Quick-moving " + __instance.draggedAmount + " items..."));
					float draggedCashAmount = __instance.draggedCashAmount;
					float num = 0f;
					for (int i = 0; i < list.Count; i++)
					{
						if (num >= (float)__instance.draggedAmount)
						{
							break;
						}
						ItemSlot val = list[i];
						if (val.ItemInstance != null)
						{
							if (Utils.Is<CashInstance>((object)val.ItemInstance, out CashInstance result2))
							{
								float num2 = 0f;
								num2 = ((!Utils.Is<CashSlot>((object)val, out CashSlot _)) ? Mathf.Min(draggedCashAmount, (float)CashItemLimit - result2.Balance) : Mathf.Min(draggedCashAmount, float.MaxValue - result2.Balance));
								result2.ChangeBalance(num2);
								val.ReplicateStoredInstance();
								num += num2;
							}
						}
						else
						{
							if (!Utils.Is<CashInstance>((object)Registry.GetItem("cash").GetDefaultInstance(1), out CashInstance result4))
							{
								Logger.Error("StartDragCash: failed to get default CashInstance");
								return false;
							}
							result4.SetBalance(__instance.draggedCashAmount, false);
							val.SetStoredItem((ItemInstance)(object)result4, false);
							num += __instance.draggedCashAmount;
						}
					}
					if (num >= result.Balance)
					{
						__instance.draggedSlot.assignedSlot.ClearStoredInstance(false);
					}
					else
					{
						result.ChangeBalance(0f - num);
						__instance.draggedSlot.assignedSlot.ReplicateStoredInstance();
					}
				}
				if (__instance.onItemMoved != null)
				{
					Logger.Debug("StartDragCash: invoking onItemMoved");
					__instance.onItemMoved.Invoke();
				}
				__instance.draggedSlot = null;
			}
			else
			{
				Logger.Debug("StartDragCash: standard drag");
				if (__instance.onDragStart != null)
				{
					Logger.Debug("StartDragCash: invoking onDragStart");
					__instance.onDragStart.Invoke();
				}
				if (__instance.draggedSlot.assignedSlot != PlayerSingleton<PlayerInventory>.Instance.cashSlot)
				{
					Logger.Debug("StartDragCash: play cash slot hint anim");
					__instance.CashSlotHintAnim.Play();
				}
				__instance.tempIcon = __instance.draggedSlot.DuplicateIcon(((Component)Singleton<HUD>.Instance).transform, __instance.draggedAmount);
				((TMP_Text)((Component)((Transform)__instance.tempIcon).Find("Balance")).GetComponent<TextMeshProUGUI>()).text = MoneyManager.FormatAmount(__instance.draggedCashAmount, false, false);
				__instance.draggedSlot.IsBeingDragged = true;
				if (__instance.draggedCashAmount >= result.Balance)
				{
					Logger.Debug("StartDragCash: hide dragged slot");
					__instance.draggedSlot.SetVisible(false);
				}
				else
				{
					Logger.Debug("StartDragCash: update cash balance display");
					if (Utils.Is<ItemUI_Cash>((object)__instance.draggedSlot.ItemUI, out ItemUI_Cash result5))
					{
						result5.SetDisplayedBalance(result.Balance - __instance.draggedCashAmount);
					}
					else
					{
						Logger.Debug("StartDragCash: draggedSlot is not ItemUI_Cash, cannot update balance display");
					}
				}
			}
			Logger.Debug("StartDragCash: end");
			return false;
		}

		[HarmonyPatch("EndCashDrag")]
		[HarmonyPrefix]
		private static bool EndCashDrag(ItemUIManager __instance)
		{
			CashInstance val = null;
			if ((Object)(object)__instance.draggedSlot != (Object)null && __instance.draggedSlot.assignedSlot != null)
			{
				if (!Utils.Is<CashInstance>((object)__instance.draggedSlot.assignedSlot.ItemInstance, out CashInstance result))
				{
					Logger.Error("EndCashDrag: draggedSlot.assignedSlot.ItemInstance is not CashInstance");
					return true;
				}
				val = result;
			}
			if (val == null)
			{
				Logger.Error("EndCashDrag: cashInstance is null");
				return true;
			}
			__instance.CashSlotHintAnim.Stop();
			__instance.CashSlotHintAnimCanvasGroup.alpha = 0f;
			bool flag = false;
			ItemSlotUI hoveredSlot = __instance.HoveredSlot;
			ItemSlot val2 = ((hoveredSlot != null) ? hoveredSlot.assignedSlot : null);
			ItemSlotUI draggedSlot = __instance.draggedSlot;
			object obj;
			if (draggedSlot == null)
			{
				obj = null;
			}
			else
			{
				ItemSlot assignedSlot = draggedSlot.assignedSlot;
				obj = ((assignedSlot != null) ? assignedSlot.ItemInstance : null);
			}
			ItemInstance val3 = (ItemInstance)obj;
			if (__instance.CanDragFromSlot(__instance.draggedSlot) && (Object)(object)__instance.HoveredSlot != (Object)null && __instance.CanCashBeDraggedIntoSlot(__instance.HoveredSlot) && val2 != null && val3 != null && !val2.IsLocked && !val2.IsAddLocked)
			{
				MethodInfo method = ((object)val2).GetType().GetMethod("DoesItemMatchHardFilters");
				MethodInfo method2 = ((object)val2).GetType().GetMethod("DoesItemMatchPlayerFilters");
				if (method != null && method2 != null)
				{
					bool flag2 = (bool)method.Invoke(val2, new object[1] { val3 });
					bool flag3 = (bool)method2.Invoke(val2, new object[1] { val3 });
					flag = flag2 && flag3;
				}
				else
				{
					MethodInfo method3 = ((object)val2).GetType().GetMethod("DoesItemMatchFilters");
					if (method3 != null)
					{
						flag = (bool)method3.Invoke(val2, new object[1] { val3 });
					}
				}
			}
			if (flag)
			{
				if (Utils.Is<HotbarSlot>((object)__instance.HoveredSlot.assignedSlot, out HotbarSlot _) && !Utils.Is<CashSlot>((object)__instance.HoveredSlot.assignedSlot, out CashSlot result3))
				{
					__instance.HoveredSlot = (ItemSlotUI)(object)((Component)Singleton<HUD>.Instance.cashSlotUI).GetComponent<CashSlotUI>();
				}
				float num = Mathf.Min(__instance.draggedCashAmount, val.Balance);
				if (num > 0f)
				{
					float num2 = num;
					if (__instance.HoveredSlot.assignedSlot.ItemInstance != null)
					{
						if (!Utils.Is<CashInstance>((object)__instance.HoveredSlot.assignedSlot.ItemInstance, out CashInstance result4))
						{
							Logger.Error("EndCashDrag: HoveredSlot.assignedSlot.ItemInstance is not CashInstance");
						}
						num2 = ((!Utils.Is<CashSlot>((object)__instance.HoveredSlot.assignedSlot, out result3)) ? Mathf.Min(num, (float)CashItemLimit - result4.Balance) : Mathf.Min(num, float.MaxValue - result4.Balance));
						result4.ChangeBalance(num2);
						__instance.HoveredSlot.assignedSlot.ReplicateStoredInstance();
					}
					else
					{
						if (!Utils.Is<CashInstance>((object)Registry.GetItem("cash").GetDefaultInstance(1), out CashInstance result5))
						{
							Logger.Error("EndCashDrag: failed to get default CashInstance");
						}
						result5.SetBalance(num2, false);
						__instance.HoveredSlot.assignedSlot.SetStoredItem((ItemInstance)(object)result5, false);
					}
					if (num2 >= val.Balance)
					{
						__instance.draggedSlot.assignedSlot.ClearStoredInstance(false);
					}
					else
					{
						val.ChangeBalance(0f - num2);
						__instance.draggedSlot.assignedSlot.ReplicateStoredInstance();
					}
				}
			}
			__instance.draggedSlot.SetVisible(true);
			__instance.draggedSlot.UpdateUI();
			__instance.draggedSlot.IsBeingDragged = false;
			__instance.draggedSlot = null;
			Object.Destroy((Object)(object)((Component)__instance.tempIcon).gameObject);
			Singleton<CursorManager>.Instance.SetCursorAppearance((ECursorType)0);
			return false;
		}

		[HarmonyPatch("UpdateCashDragAmount")]
		[HarmonyPrefix]
		private static bool UpdateCashDragAmount(ItemUIManager __instance, CashInstance instance)
		{
			float[] array = new float[3] { 50f, 10f, 1f };
			float[] array2 = new float[3] { 100f, 10f, 1f };
			float num = 0f;
			if (GameInput.MouseScrollDelta > 0f)
			{
				for (int i = 0; i < array.Length; i++)
				{
					if (__instance.draggedCashAmount >= array2[i])
					{
						num = array[i];
						break;
					}
				}
			}
			else if (GameInput.MouseScrollDelta < 0f)
			{
				for (int j = 0; j < array.Length; j++)
				{
					if (__instance.draggedCashAmount > array2[j])
					{
						num = 0f - array[j];
						break;
					}
				}
			}
			if (num != 0f)
			{
				__instance.draggedCashAmount = Mathf.Clamp(__instance.draggedCashAmount + num, 1f, Mathf.Min(instance.Balance, (float)CashItemLimit));
			}
			return false;
		}

		static CashPatches()
		{
			ItemRegister? obj = Singleton<Registry>.Instance.ItemRegistry.AsEnumerable<ItemRegister>().FirstOrDefault((Func<ItemRegister, bool>)((ItemRegister x) => x.ID == "cash"));
			int? obj2;
			if (obj == null)
			{
				obj2 = null;
			}
			else
			{
				ItemDefinition definition = obj.Definition;
				obj2 = ((definition != null) ? new int?(definition.StackLimit) : null);
			}
			int? num = obj2;
			CashItemLimit = num.GetValueOrDefault(1000);
			Logger = Melon<CustomStack>.Logger;
		}
	}
}
namespace CustomStack.Helpers
{
	public static class MelonLoggerExtensions
	{
		public static void Debug(this Instance logger, string message, bool stacktrace = true)
		{
		}

		private static string GetLoggerName(Instance logger)
		{
			return typeof(Instance).GetField("Name", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(logger) as string;
		}

		private static void InvokeNativeMsg(Color namesectionColor, Color textColor, string nameSection, string message)
		{
			typeof(MelonLogger).GetMethod("NativeMsg", BindingFlags.Static | BindingFlags.NonPublic)?.Invoke(null, new object[5]
			{
				namesectionColor,
				textColor,
				nameSection,
				message ?? "null",
				false
			});
		}

		private static string GetCallerInfo()
		{
			StackTrace stackTrace = new StackTrace();
			for (int i = 2; i < stackTrace.FrameCount; i++)
			{
				StackFrame frame = stackTrace.GetFrame(i);
				MethodBase method = frame.GetMethod();
				if (!(method?.DeclaringType == null))
				{
					return method.DeclaringType.FullName + "." + method.Name;
				}
			}
			return "unknown";
		}
	}
	public static class Il2CppListExtensions
	{
		public static IEnumerable<T> AsEnumerable<T>(this List<T> list)
		{
			return list ?? new List<T>();
		}

		public static List<T> ToIl2CppList<T>(this IEnumerable<T> source)
		{
			List<T> val = new List<T>();
			foreach (T item in source)
			{
				val.Add(item);
			}
			return val;
		}

		public static List<T> ConvertToList<T>(List<T> il2CppList)
		{
			List<T> list = new List<T>();
			T[] collection = Il2CppArrayBase<T>.op_Implicit(il2CppList.ToArray());
			list.AddRange(collection);
			return list;
		}

		public static IEnumerable<T> AsEnumerable<T>(this List<T> list)
		{
			IEnumerable<T> result;
			if (list != null)
			{
				result = ((IEnumerable<T>)list._items).Take(list._size);
			}
			else
			{
				IEnumerable<T> enumerable = Array.Empty<T>();
				result = enumerable;
			}
			return result;
		}
	}
	public static class Utils
	{
		[CompilerGenerated]
		private sealed class <WaitForNetwork>d__6 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public IEnumerator routine;

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

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

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

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (!InstanceFinder.IsServer && !InstanceFinder.IsClient)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				MelonCoroutines.Start(routine);
				return false;
			}

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

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

		[CompilerGenerated]
		private sealed class <WaitForNetworkSingleton>d__8<T> : IEnumerator<object>, IEnumerator, IDisposable where T : notnull, NetworkSingleton<T>
		{
			private int <>1__state;

			private object <>2__current;

			public IEnumerator coroutine;

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

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

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

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					goto IL_0044;
				case 1:
					<>1__state = -1;
					goto IL_0044;
				case 2:
					{
						<>1__state = -1;
						return false;
					}
					IL_0044:
					if (!NetworkSingleton<T>.InstanceExists)
					{
						<>2__current = null;
						<>1__state = 1;
						return true;
					}
					<>2__current = coroutine;
					<>1__state = 2;
					return true;
				}
			}

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

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

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

			private object <>2__current;

			public object obj;

			public float timeout;

			public Action onTimeout;

			public Action onFinish;

			private float <startTime>5__1;

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

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

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

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<startTime>5__1 = Time.time;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (obj == null)
				{
					if (!float.IsNaN(timeout) && Time.time - <startTime>5__1 > timeout)
					{
						onTimeout?.Invoke();
						return false;
					}
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				onFinish?.Invoke();
				return false;
			}

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

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

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

			private object <>2__current;

			public IEnumerator routine;

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

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

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

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if ((Object)(object)Player.Local == (Object)null || (Object)(object)((Component)Player.Local).gameObject == (Object)null)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				MelonCoroutines.Start(routine);
				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 static readonly Instance Logger = new Instance("CustomStack-Utils");

		public static T FindObjectByName<T>(string objectName) where T : Object
		{
			try
			{
				foreach (T item in Resources.FindObjectsOfTypeAll<T>())
				{
					if (((Object)item).name != objectName)
					{
						continue;
					}
					Logger.Debug($"Found {typeof(T).Name} '{objectName}' directly in loaded objects");
					return item;
				}
				return default(T);
			}
			catch (Exception ex)
			{
				Logger.Error($"Error finding {typeof(T).Name} '{objectName}': {ex.Message}");
				return default(T);
			}
		}

		public static List<T> GetAllComponentsInChildrenRecursive<T>(GameObject obj) where T : Component
		{
			List<T> list = new List<T>();
			if ((Object)(object)obj == (Object)null)
			{
				return list;
			}
			T[] array = Il2CppArrayBase<T>.op_Implicit(obj.GetComponents<T>());
			if (array.Length != 0)
			{
				list.AddRange(array);
			}
			for (int i = 0; i < obj.transform.childCount; i++)
			{
				Transform child = obj.transform.GetChild(i);
				list.AddRange(GetAllComponentsInChildrenRecursive<T>(((Component)child).gameObject));
			}
			return list;
		}

		public static bool Is<T>(object obj, out T result) where T : Object
		{
			Object val = (Object)((obj is Object) ? obj : null);
			if (val != null)
			{
				Type val2 = Il2CppType.Of<T>();
				Type il2CppType = val.GetIl2CppType();
				if (val2.IsAssignableFrom(il2CppType))
				{
					result = ((Il2CppObjectBase)val).TryCast<T>();
					return result != null;
				}
			}
			result = default(T);
			return false;
		}

		public static List<StorableItemDefinition> GetAllStorableItemDefinitions()
		{
			List<ItemRegister> list = Il2CppListExtensions.ConvertToList<ItemRegister>(Singleton<Registry>.Instance.ItemRegistry);
			List<StorableItemDefinition> list2 = new List<StorableItemDefinition>();
			foreach (ItemRegister item in list)
			{
				if (Utils.Is<StorableItemDefinition>((object)item.Definition, out StorableItemDefinition result))
				{
					list2.Add(result);
				}
				else
				{
					Logger.Warning("Definition " + ((object)item.Definition)?.GetType().FullName + " is not a StorableItemDefinition");
				}
			}
			return list2.ToList();
		}

		[IteratorStateMachine(typeof(<WaitForPlayer>d__5))]
		public static IEnumerator WaitForPlayer(IEnumerator routine)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForPlayer>d__5(0)
			{
				routine = routine
			};
		}

		[IteratorStateMachine(typeof(<WaitForNetwork>d__6))]
		public static IEnumerator WaitForNetwork(IEnumerator routine)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForNetwork>d__6(0)
			{
				routine = routine
			};
		}

		[IteratorStateMachine(typeof(<WaitForNotNull>d__7))]
		public static IEnumerator WaitForNotNull(object? obj, float timeout = float.NaN, Action onTimeout = null, Action onFinish = null)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForNotNull>d__7(0)
			{
				obj = obj,
				timeout = timeout,
				onTimeout = onTimeout,
				onFinish = onFinish
			};
		}

		[IteratorStateMachine(typeof(<WaitForNetworkSingleton>d__8<>))]
		public static IEnumerator WaitForNetworkSingleton<T>(IEnumerator coroutine) where T : NetworkSingleton<T>
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForNetworkSingleton>d__8<T>(0)
			{
				coroutine = coroutine
			};
		}
	}
}

CustomStack-Mono.dll

Decompiled 2 weeks ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using System.Security;
using System.Security.Permissions;
using CustomStack;
using CustomStack.Helpers;
using FishNet;
using HarmonyLib;
using MelonLoader;
using MelonLoader.Preferences;
using MelonLoader.Utils;
using Microsoft.CodeAnalysis;
using ScheduleOne;
using ScheduleOne.DevUtilities;
using ScheduleOne.ItemFramework;
using ScheduleOne.Money;
using ScheduleOne.PlayerScripts;
using ScheduleOne.UI;
using ScheduleOne.UI.Items;
using TMPro;
using UnityEngine;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: MelonInfo(typeof(global::CustomStack.CustomStack), "CustomStack", "1.1.4", "k073l", null)]
[assembly: MelonColor(1, 255, 0, 0)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: IgnoresAccessChecksTo("Assembly-CSharp")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("CustomStack-Mono")]
[assembly: AssemblyConfiguration("Release Mono")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0+7c51b5d3baf0c96439bf2364e196b05b440987b9")]
[assembly: AssemblyProduct("CustomStack-Mono")]
[assembly: AssemblyTitle("CustomStack-Mono")]
[assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)]
[assembly: AssemblyVersion("1.0.0.0")]
[module: UnverifiableCode]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[Microsoft.CodeAnalysis.Embedded]
	[AttributeUsage(AttributeTargets.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.Class | AttributeTargets.Struct | AttributeTargets.Method | AttributeTargets.Interface | AttributeTargets.Delegate, AllowMultiple = false, Inherited = false)]
	internal sealed class NullableContextAttribute : Attribute
	{
		public readonly byte Flag;

		public NullableContextAttribute(byte P_0)
		{
			Flag = 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 CustomStack
{
	public static class BuildInfo
	{
		public const string Name = "CustomStack";

		public const string Description = "Custom stack limits, per item";

		public const string Author = "k073l";

		public const string Version = "1.1.4";
	}
	public class CustomStack : MelonMod
	{
		private static Instance _logger;

		private static MelonPreferences_Category _category;

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

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

		private static bool _populatedDefaultLimits = false;

		public override void OnInitializeMelon()
		{
			_logger = ((MelonBase)this).LoggerInstance;
			_logger.Msg("CustomStack initialized.");
			_category = MelonPreferences.CreateCategory("CustomStack");
			_category.SetFilePath(Path.Combine(MelonEnvironment.UserDataDirectory, "CustomStack.cfg"));
		}

		public override void OnSceneWasInitialized(int buildIndex, string sceneName)
		{
			if (sceneName == "Menu")
			{
				LoadAllItems();
			}
			_logger.Debug("Scene loaded: " + sceneName);
		}

		private static void LoadAllItems()
		{
			if (_populatedDefaultLimits)
			{
				_logger.Msg("Item limits already set, skipping.");
				return;
			}
			_logger.Msg("Loading item stack limits...");
			IEnumerable<ItemRegister> enumerable = Singleton<Registry>.Instance.ItemRegistry.AsEnumerable();
			_category.LoadFromFile(false);
			foreach (ItemRegister item in enumerable)
			{
				string iD = item.ID;
				int stackLimit = item.Definition.StackLimit;
				if (!Entries.ContainsKey(iD))
				{
					MelonPreferences_Entry<int> value = _category.CreateEntry<int>(iD, stackLimit, (string)null, (string)null, false, false, (ValueValidator)null, (string)null);
					Entries[iD] = value;
				}
				if (!_populatedDefaultLimits && !_defaultLimits.ContainsKey(iD))
				{
					_defaultLimits[iD] = stackLimit;
				}
				MelonPreferences_Entry<int> val = Entries[iD];
				int value2 = val.Value;
				if (iD == "cash")
				{
					if (value2 == _defaultLimits[iD])
					{
						_logger.Msg("Cash stack limit not configured, forcing runtime limit to 1k (config not changed).");
						item.Definition.StackLimit = 1000;
						continue;
					}
					item.Definition.StackLimit = value2;
					if (value2 != _defaultLimits[iD])
					{
						_logger.Msg($"cash limit overridden by user: {_defaultLimits[iD]} → {value2}");
					}
				}
				else
				{
					item.Definition.StackLimit = value2;
					if (value2 != _defaultLimits[iD])
					{
						_logger.Msg($"{iD} limit overridden: {_defaultLimits[iD]} → {value2}");
					}
				}
			}
			_populatedDefaultLimits = true;
		}
	}
}
namespace CustomStack.Patches
{
	[HarmonyPatch(typeof(ItemUIManager))]
	public static class CashPatches
	{
		private static int CashItemLimit = (Singleton<Registry>.Instance.ItemRegistry.AsEnumerable().FirstOrDefault((Func<ItemRegister, bool>)((ItemRegister x) => x.ID == "cash"))?.Definition?.StackLimit).GetValueOrDefault(1000);

		private static Instance Logger = Melon<CustomStack>.Logger;

		[HarmonyPatch("StartDragCash")]
		[HarmonyPrefix]
		private static bool StartDragCash(ItemUIManager __instance)
		{
			//IL_00cc: Unknown result type (might be due to invalid IL or missing references)
			//IL_00db: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e0: Unknown result type (might be due to invalid IL or missing references)
			//IL_00e5: Unknown result type (might be due to invalid IL or missing references)
			Logger.Debug("StartDragCash: top");
			ItemInstance itemInstance = __instance.draggedSlot.assignedSlot.ItemInstance;
			if (!Utils.Is<CashInstance>(itemInstance, out var result))
			{
				Logger.Debug("StartDragCash: cashInstance is null");
			}
			Logger.Debug("StartDragCash: got cashInstance");
			__instance.draggedCashAmount = Mathf.Min(result.Balance, (float)CashItemLimit);
			__instance.draggedAmount = 1;
			Logger.Debug("Set draggedCashAmount and draggedAmount");
			if (GameInput.GetButtonDown((ButtonCode)1))
			{
				Logger.Debug("StartDragCash: secondary click");
				__instance.draggedAmount = 1;
				__instance.draggedCashAmount = Mathf.Min(result.Balance, Mathf.Floor((float)CashItemLimit / 10f));
				__instance.mouseOffset += new Vector2(-10f, -15f);
				__instance.customDragAmount = true;
			}
			Logger.Debug("StartDragCash: draggedAmount check");
			if (__instance.draggedCashAmount <= 0f)
			{
				Logger.Debug("StartDragCash: no cash to drag");
				__instance.draggedSlot = null;
			}
			else if (GameInput.GetButton((ButtonCode)23) && __instance.QuickMoveEnabled)
			{
				Logger.Debug("StartDragCash: quickmove");
				List<ItemSlot> quickMoveSlots = __instance.GetQuickMoveSlots(__instance.draggedSlot.assignedSlot);
				if (quickMoveSlots.Count > 0)
				{
					Logger.Debug("StartDragCash: quickmove slots found");
					Debug.Log((object)("Quick-moving " + __instance.draggedAmount + " items..."));
					float draggedCashAmount = __instance.draggedCashAmount;
					float num = 0f;
					for (int i = 0; i < quickMoveSlots.Count; i++)
					{
						if (num >= (float)__instance.draggedAmount)
						{
							break;
						}
						ItemSlot val = quickMoveSlots[i];
						if (val.ItemInstance != null)
						{
							if (Utils.Is<CashInstance>(val.ItemInstance, out var result2))
							{
								float num2 = 0f;
								num2 = ((!Utils.Is<CashSlot>(val, out var _)) ? Mathf.Min(draggedCashAmount, (float)CashItemLimit - result2.Balance) : Mathf.Min(draggedCashAmount, float.MaxValue - result2.Balance));
								result2.ChangeBalance(num2);
								val.ReplicateStoredInstance();
								num += num2;
							}
						}
						else
						{
							if (!Utils.Is<CashInstance>(Registry.GetItem("cash").GetDefaultInstance(1), out var result4))
							{
								Logger.Error("StartDragCash: failed to get default CashInstance");
								return false;
							}
							result4.SetBalance(__instance.draggedCashAmount, false);
							val.SetStoredItem((ItemInstance)(object)result4, false);
							num += __instance.draggedCashAmount;
						}
					}
					if (num >= result.Balance)
					{
						__instance.draggedSlot.assignedSlot.ClearStoredInstance(false);
					}
					else
					{
						result.ChangeBalance(0f - num);
						__instance.draggedSlot.assignedSlot.ReplicateStoredInstance();
					}
				}
				if (__instance.onItemMoved != null)
				{
					Logger.Debug("StartDragCash: invoking onItemMoved");
					__instance.onItemMoved.Invoke();
				}
				__instance.draggedSlot = null;
			}
			else
			{
				Logger.Debug("StartDragCash: standard drag");
				if (__instance.onDragStart != null)
				{
					Logger.Debug("StartDragCash: invoking onDragStart");
					__instance.onDragStart.Invoke();
				}
				if (__instance.draggedSlot.assignedSlot != PlayerSingleton<PlayerInventory>.Instance.cashSlot)
				{
					Logger.Debug("StartDragCash: play cash slot hint anim");
					__instance.CashSlotHintAnim.Play();
				}
				__instance.tempIcon = __instance.draggedSlot.DuplicateIcon(((Component)Singleton<HUD>.Instance).transform, __instance.draggedAmount);
				((TMP_Text)((Component)((Transform)__instance.tempIcon).Find("Balance")).GetComponent<TextMeshProUGUI>()).text = MoneyManager.FormatAmount(__instance.draggedCashAmount, false, false);
				__instance.draggedSlot.IsBeingDragged = true;
				if (__instance.draggedCashAmount >= result.Balance)
				{
					Logger.Debug("StartDragCash: hide dragged slot");
					__instance.draggedSlot.SetVisible(false);
				}
				else
				{
					Logger.Debug("StartDragCash: update cash balance display");
					if (Utils.Is<ItemUI_Cash>(__instance.draggedSlot.ItemUI, out var result5))
					{
						result5.SetDisplayedBalance(result.Balance - __instance.draggedCashAmount);
					}
					else
					{
						Logger.Debug("StartDragCash: draggedSlot is not ItemUI_Cash, cannot update balance display");
					}
				}
			}
			Logger.Debug("StartDragCash: end");
			return false;
		}

		[HarmonyPatch("EndCashDrag")]
		[HarmonyPrefix]
		private static bool EndCashDrag(ItemUIManager __instance)
		{
			CashInstance val = null;
			if ((Object)(object)__instance.draggedSlot != (Object)null && __instance.draggedSlot.assignedSlot != null)
			{
				if (!Utils.Is<CashInstance>(__instance.draggedSlot.assignedSlot.ItemInstance, out var result))
				{
					Logger.Error("EndCashDrag: draggedSlot.assignedSlot.ItemInstance is not CashInstance");
					return true;
				}
				val = result;
			}
			if (val == null)
			{
				Logger.Error("EndCashDrag: cashInstance is null");
				return true;
			}
			__instance.CashSlotHintAnim.Stop();
			__instance.CashSlotHintAnimCanvasGroup.alpha = 0f;
			bool flag = false;
			ItemSlotUI hoveredSlot = __instance.HoveredSlot;
			ItemSlot val2 = ((hoveredSlot != null) ? hoveredSlot.assignedSlot : null);
			ItemSlotUI draggedSlot = __instance.draggedSlot;
			object obj;
			if (draggedSlot == null)
			{
				obj = null;
			}
			else
			{
				ItemSlot assignedSlot = draggedSlot.assignedSlot;
				obj = ((assignedSlot != null) ? assignedSlot.ItemInstance : null);
			}
			ItemInstance val3 = (ItemInstance)obj;
			if (__instance.CanDragFromSlot(__instance.draggedSlot) && (Object)(object)__instance.HoveredSlot != (Object)null && __instance.CanCashBeDraggedIntoSlot(__instance.HoveredSlot) && val2 != null && val3 != null && !val2.IsLocked && !val2.IsAddLocked)
			{
				MethodInfo method = ((object)val2).GetType().GetMethod("DoesItemMatchHardFilters");
				MethodInfo method2 = ((object)val2).GetType().GetMethod("DoesItemMatchPlayerFilters");
				if (method != null && method2 != null)
				{
					bool flag2 = (bool)method.Invoke(val2, new object[1] { val3 });
					bool flag3 = (bool)method2.Invoke(val2, new object[1] { val3 });
					flag = flag2 && flag3;
				}
				else
				{
					MethodInfo method3 = ((object)val2).GetType().GetMethod("DoesItemMatchFilters");
					if (method3 != null)
					{
						flag = (bool)method3.Invoke(val2, new object[1] { val3 });
					}
				}
			}
			if (flag)
			{
				if (Utils.Is<HotbarSlot>(__instance.HoveredSlot.assignedSlot, out var _) && !Utils.Is<CashSlot>(__instance.HoveredSlot.assignedSlot, out var result3))
				{
					__instance.HoveredSlot = (ItemSlotUI)(object)((Component)Singleton<HUD>.Instance.cashSlotUI).GetComponent<CashSlotUI>();
				}
				float num = Mathf.Min(__instance.draggedCashAmount, val.Balance);
				if (num > 0f)
				{
					float num2 = num;
					if (__instance.HoveredSlot.assignedSlot.ItemInstance != null)
					{
						if (!Utils.Is<CashInstance>(__instance.HoveredSlot.assignedSlot.ItemInstance, out var result4))
						{
							Logger.Error("EndCashDrag: HoveredSlot.assignedSlot.ItemInstance is not CashInstance");
						}
						num2 = ((!Utils.Is<CashSlot>(__instance.HoveredSlot.assignedSlot, out result3)) ? Mathf.Min(num, (float)CashItemLimit - result4.Balance) : Mathf.Min(num, float.MaxValue - result4.Balance));
						result4.ChangeBalance(num2);
						__instance.HoveredSlot.assignedSlot.ReplicateStoredInstance();
					}
					else
					{
						if (!Utils.Is<CashInstance>(Registry.GetItem("cash").GetDefaultInstance(1), out var result5))
						{
							Logger.Error("EndCashDrag: failed to get default CashInstance");
						}
						result5.SetBalance(num2, false);
						__instance.HoveredSlot.assignedSlot.SetStoredItem((ItemInstance)(object)result5, false);
					}
					if (num2 >= val.Balance)
					{
						__instance.draggedSlot.assignedSlot.ClearStoredInstance(false);
					}
					else
					{
						val.ChangeBalance(0f - num2);
						__instance.draggedSlot.assignedSlot.ReplicateStoredInstance();
					}
				}
			}
			__instance.draggedSlot.SetVisible(true);
			__instance.draggedSlot.UpdateUI();
			__instance.draggedSlot.IsBeingDragged = false;
			__instance.draggedSlot = null;
			Object.Destroy((Object)(object)((Component)__instance.tempIcon).gameObject);
			Singleton<CursorManager>.Instance.SetCursorAppearance((ECursorType)0);
			return false;
		}

		[HarmonyPatch("UpdateCashDragAmount")]
		[HarmonyPrefix]
		private static bool UpdateCashDragAmount(ItemUIManager __instance, CashInstance instance)
		{
			float[] array = new float[3] { 50f, 10f, 1f };
			float[] array2 = new float[3] { 100f, 10f, 1f };
			float num = 0f;
			if (GameInput.MouseScrollDelta > 0f)
			{
				for (int i = 0; i < array.Length; i++)
				{
					if (__instance.draggedCashAmount >= array2[i])
					{
						num = array[i];
						break;
					}
				}
			}
			else if (GameInput.MouseScrollDelta < 0f)
			{
				for (int j = 0; j < array.Length; j++)
				{
					if (__instance.draggedCashAmount > array2[j])
					{
						num = 0f - array[j];
						break;
					}
				}
			}
			if (num != 0f)
			{
				__instance.draggedCashAmount = Mathf.Clamp(__instance.draggedCashAmount + num, 1f, Mathf.Min(instance.Balance, (float)CashItemLimit));
			}
			return false;
		}
	}
}
namespace CustomStack.Helpers
{
	public static class MelonLoggerExtensions
	{
		public static void Debug(this Instance logger, string message, bool stacktrace = true)
		{
		}

		private static string GetLoggerName(Instance logger)
		{
			return typeof(Instance).GetField("Name", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(logger) as string;
		}

		private static void InvokeNativeMsg(Color namesectionColor, Color textColor, string nameSection, string message)
		{
			typeof(MelonLogger).GetMethod("NativeMsg", BindingFlags.Static | BindingFlags.NonPublic)?.Invoke(null, new object[5]
			{
				namesectionColor,
				textColor,
				nameSection,
				message ?? "null",
				false
			});
		}

		private static string GetCallerInfo()
		{
			StackTrace stackTrace = new StackTrace();
			for (int i = 2; i < stackTrace.FrameCount; i++)
			{
				StackFrame frame = stackTrace.GetFrame(i);
				MethodBase method = frame.GetMethod();
				if (!(method?.DeclaringType == null))
				{
					return method.DeclaringType.FullName + "." + method.Name;
				}
			}
			return "unknown";
		}
	}
	public static class Il2CppListExtensions
	{
		public static IEnumerable<T> AsEnumerable<T>(this List<T> list)
		{
			return list ?? new List<T>();
		}
	}
	public static class Utils
	{
		[CompilerGenerated]
		private sealed class <WaitForNetwork>d__6 : IEnumerator<object>, IEnumerator, IDisposable
		{
			private int <>1__state;

			private object <>2__current;

			public IEnumerator routine;

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

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

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

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (!InstanceFinder.IsServer && !InstanceFinder.IsClient)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				MelonCoroutines.Start(routine);
				return false;
			}

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

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

		[CompilerGenerated]
		private sealed class <WaitForNetworkSingleton>d__8<T> : IEnumerator<object>, IEnumerator, IDisposable where T : notnull, NetworkSingleton<T>
		{
			private int <>1__state;

			private object <>2__current;

			public IEnumerator coroutine;

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

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

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

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					goto IL_0044;
				case 1:
					<>1__state = -1;
					goto IL_0044;
				case 2:
					{
						<>1__state = -1;
						return false;
					}
					IL_0044:
					if (!NetworkSingleton<T>.InstanceExists)
					{
						<>2__current = null;
						<>1__state = 1;
						return true;
					}
					<>2__current = coroutine;
					<>1__state = 2;
					return true;
				}
			}

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

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

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

			private object <>2__current;

			public object obj;

			public float timeout;

			public Action onTimeout;

			public Action onFinish;

			private float <startTime>5__1;

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

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

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

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					<startTime>5__1 = Time.time;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if (obj == null)
				{
					if (!float.IsNaN(timeout) && Time.time - <startTime>5__1 > timeout)
					{
						onTimeout?.Invoke();
						return false;
					}
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				onFinish?.Invoke();
				return false;
			}

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

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

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

			private object <>2__current;

			public IEnumerator routine;

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

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

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

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

			private bool MoveNext()
			{
				switch (<>1__state)
				{
				default:
					return false;
				case 0:
					<>1__state = -1;
					break;
				case 1:
					<>1__state = -1;
					break;
				}
				if ((Object)(object)Player.Local == (Object)null || (Object)(object)((Component)Player.Local).gameObject == (Object)null)
				{
					<>2__current = null;
					<>1__state = 1;
					return true;
				}
				MelonCoroutines.Start(routine);
				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 static readonly Instance Logger = new Instance("CustomStack-Utils");

		public static T FindObjectByName<T>(string objectName) where T : Object
		{
			try
			{
				T[] array = Resources.FindObjectsOfTypeAll<T>();
				foreach (T val in array)
				{
					if (!(((Object)val).name != objectName))
					{
						Logger.Debug("Found " + typeof(T).Name + " '" + objectName + "' directly in loaded objects");
						return val;
					}
				}
				return default(T);
			}
			catch (Exception ex)
			{
				Logger.Error("Error finding " + typeof(T).Name + " '" + objectName + "': " + ex.Message);
				return default(T);
			}
		}

		public static List<T> GetAllComponentsInChildrenRecursive<T>(GameObject obj) where T : Component
		{
			List<T> list = new List<T>();
			if ((Object)(object)obj == (Object)null)
			{
				return list;
			}
			T[] components = obj.GetComponents<T>();
			if (components.Length != 0)
			{
				list.AddRange(components);
			}
			for (int i = 0; i < obj.transform.childCount; i++)
			{
				Transform child = obj.transform.GetChild(i);
				list.AddRange(GetAllComponentsInChildrenRecursive<T>(((Component)child).gameObject));
			}
			return list;
		}

		public static bool Is<T>(object obj, out T result) where T : class
		{
			if (obj is T val)
			{
				result = val;
				return true;
			}
			result = null;
			return false;
		}

		public static List<StorableItemDefinition> GetAllStorableItemDefinitions()
		{
			List<ItemRegister> list = Singleton<Registry>.Instance.ItemRegistry.ToList();
			List<StorableItemDefinition> list2 = new List<StorableItemDefinition>();
			foreach (ItemRegister item in list)
			{
				if (Is<StorableItemDefinition>(item.Definition, out var result))
				{
					list2.Add(result);
				}
				else
				{
					Logger.Warning("Definition " + ((object)item.Definition)?.GetType().FullName + " is not a StorableItemDefinition");
				}
			}
			return list2.ToList();
		}

		[IteratorStateMachine(typeof(<WaitForPlayer>d__5))]
		public static IEnumerator WaitForPlayer(IEnumerator routine)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForPlayer>d__5(0)
			{
				routine = routine
			};
		}

		[IteratorStateMachine(typeof(<WaitForNetwork>d__6))]
		public static IEnumerator WaitForNetwork(IEnumerator routine)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForNetwork>d__6(0)
			{
				routine = routine
			};
		}

		[IteratorStateMachine(typeof(<WaitForNotNull>d__7))]
		public static IEnumerator WaitForNotNull(object? obj, float timeout = float.NaN, Action onTimeout = null, Action onFinish = null)
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForNotNull>d__7(0)
			{
				obj = obj,
				timeout = timeout,
				onTimeout = onTimeout,
				onFinish = onFinish
			};
		}

		[IteratorStateMachine(typeof(<WaitForNetworkSingleton>d__8<>))]
		public static IEnumerator WaitForNetworkSingleton<T>(IEnumerator coroutine) where T : NetworkSingleton<T>
		{
			//yield-return decompiler failed: Unexpected instruction in Iterator.Dispose()
			return new <WaitForNetworkSingleton>d__8<T>(0)
			{
				coroutine = coroutine
			};
		}
	}
}
namespace System.Runtime.CompilerServices
{
	[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)]
	internal sealed class IgnoresAccessChecksToAttribute : Attribute
	{
		public IgnoresAccessChecksToAttribute(string assemblyName)
		{
		}
	}
}