Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of CustomStack v1.1.4
CustomStack-IL2CPP.dll
Decompiled 2 weeks agousing 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 agousing 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) { } } }