Decompiled source of BiggerStacks v1.0.1

Mods/BiggerStacks.dll

Decompiled 4 hours ago
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;
using BiggerStacks;
using Il2CppInterop.Runtime.InteropTypes;
using MelonLoader;
using MelonLoader.Preferences;
using Microsoft.CodeAnalysis;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: MelonInfo(typeof(Mod), "BiggerStacks", "1.0.1", "LordValdomod", null)]
[assembly: MelonGame("TVGS", "Schedule I")]
[assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")]
[assembly: AssemblyCompany("BiggerStacks")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.1.0")]
[assembly: AssemblyInformationalVersion("1.0.1")]
[assembly: AssemblyProduct("BiggerStacks")]
[assembly: AssemblyTitle("BiggerStacks")]
[assembly: AssemblyVersion("1.0.1.0")]
[module: RefSafetyRules(11)]
namespace Microsoft.CodeAnalysis
{
	[CompilerGenerated]
	[Embedded]
	internal sealed class EmbeddedAttribute : Attribute
	{
	}
}
namespace System.Runtime.CompilerServices
{
	[CompilerGenerated]
	[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 BiggerStacks
{
	public class Mod : MelonMod
	{
		private const int MaxAllowed = 9999;

		private MelonPreferences_Entry<int> limitEntry;

		private readonly Dictionary<IntPtr, int> originals = new Dictionary<IntPtr, int>();

		private Type defType;

		private PropertyInfo stackProp;

		private MethodInfo findAll;

		private object il2cppDefType;

		private float applyAt = -1f;

		private int applied = -1;

		private static PropertyInfo timeProp;

		public override void OnInitializeMelon()
		{
			MelonPreferences_Category val = MelonPreferences.CreateCategory("BiggerStacks", "Bigger Stacks");
			limitEntry = val.CreateEntry<int>("StackLimit", 100, "Limite por slot", "Quantidade máxima por slot pra itens que já empilham (2 a 9999).", false, false, (ValueValidator)null, (string)null);
		}

		public override void OnSceneWasInitialized(int buildIndex, string sceneName)
		{
			applyAt = UnityEngine_Time() + 3f;
		}

		public override void OnUpdate()
		{
			if (applyAt < 0f || UnityEngine_Time() < applyAt)
			{
				return;
			}
			applyAt = -1f;
			try
			{
				Apply();
			}
			catch (Exception ex)
			{
				((MelonBase)this).LoggerInstance.Error("Falha ao aplicar o limite: " + ex);
			}
		}

		private void Apply()
		{
			if (!Resolve())
			{
				return;
			}
			int num = Math.Max(2, Math.Min(9999, limitEntry.Value));
			if (num != limitEntry.Value)
			{
				limitEntry.Value = num;
			}
			if (!(findAll.Invoke(null, new object[1] { il2cppDefType }) is IEnumerable enumerable))
			{
				return;
			}
			int num2 = 0;
			int num3 = 0;
			foreach (object item in enumerable)
			{
				Il2CppObjectBase val = (Il2CppObjectBase)((item is Il2CppObjectBase) ? item : null);
				if (val == null || val.Pointer == IntPtr.Zero)
				{
					continue;
				}
				object obj = Activator.CreateInstance(defType, val.Pointer);
				int num4 = (int)stackProp.GetValue(obj);
				if (!originals.TryGetValue(val.Pointer, out var value))
				{
					value = (originals[val.Pointer] = num4);
				}
				if (value > 1)
				{
					num3++;
					if (num4 != num)
					{
						stackProp.SetValue(obj, num);
						num2++;
					}
				}
			}
			if (num2 > 0 || applied != num)
			{
				((MelonBase)this).LoggerInstance.Msg($"Limite de {num} por slot aplicado em {num3} itens ({num2} alterados).");
			}
			applied = num;
		}

		private bool Resolve()
		{
			if (stackProp != null)
			{
				return true;
			}
			defType = FindType("Il2CppScheduleOne.Core.Items.Framework.BaseItemDefinition") ?? AppDomain.CurrentDomain.GetAssemblies().SelectMany(delegate(Assembly a)
			{
				try
				{
					return a.GetTypes();
				}
				catch (ReflectionTypeLoadException ex)
				{
					return ex.Types.Where((Type t) => t != null);
				}
				catch
				{
					return Array.Empty<Type>();
				}
			}).FirstOrDefault((Type t) => t.Name == "ItemDefinition" && t.FullName != null && t.FullName.StartsWith("Il2CppScheduleOne", StringComparison.Ordinal));
			stackProp = defType?.GetProperty("StackLimit", BindingFlags.Instance | BindingFlags.Public);
			findAll = FindType("UnityEngine.Resources")?.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo m) => m.Name == "FindObjectsOfTypeAll" && !m.IsGenericMethod && m.GetParameters().Length == 1);
			if (defType == null || stackProp == null || findAll == null)
			{
				((MelonBase)this).LoggerInstance.Error("BaseItemDefinition.StackLimit não encontrado. Versão do jogo incompatível?");
				stackProp = null;
				return false;
			}
			MethodInfo methodInfo = (from m in typeof(Il2CppObjectBase).Assembly.GetType("Il2CppInterop.Runtime.Il2CppType")?.GetMethods(BindingFlags.Static | BindingFlags.Public)
				where m.Name == "From" && m.GetParameters().FirstOrDefault()?.ParameterType == typeof(Type)
				orderby m.GetParameters().Length
				select m).FirstOrDefault();
			il2cppDefType = methodInfo?.Invoke(null, methodInfo.GetParameters().Select((ParameterInfo p, int i) => (i != 0) ? ((!(p.ParameterType == typeof(bool))) ? p.DefaultValue : ((object)false)) : defType).ToArray());
			if (il2cppDefType == null)
			{
				((MelonBase)this).LoggerInstance.Error("Não foi possível resolver o tipo IL2CPP de ItemDefinition.");
				stackProp = null;
				return false;
			}
			return true;
		}

		private static float UnityEngine_Time()
		{
			if (timeProp == null)
			{
				timeProp = FindType("UnityEngine.Time")?.GetProperty("realtimeSinceStartup", BindingFlags.Static | BindingFlags.Public);
			}
			if (!(timeProp == null))
			{
				return (float)timeProp.GetValue(null);
			}
			return 0f;
		}

		private static Type FindType(string fullName)
		{
			Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
			foreach (Assembly assembly in assemblies)
			{
				Type type = null;
				try
				{
					type = assembly.GetType(fullName, throwOnError: false);
				}
				catch
				{
				}
				if (type != null)
				{
					return type;
				}
			}
			return null;
		}
	}
}