Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of BiggerStations v1.1.0
Mods/BiggerStations.dll
Decompiled 5 hours agousing 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 BiggerStations; 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), "BiggerStations", "1.1.0", "LordValdomod", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("BiggerStations")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.1.0.0")] [assembly: AssemblyInformationalVersion("1.1.0")] [assembly: AssemblyProduct("BiggerStations")] [assembly: AssemblyTitle("BiggerStations")] [assembly: AssemblyVersion("1.1.0.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 BiggerStations { public class Mod : MelonMod { private const int MaxAllowed = 9999; private const int IntervalMs = 10000; private static readonly (string type, string field)[] Targets = new(string, string)[2] { ("Il2CppScheduleOne.ObjectScripts.DryingRack", "ItemCapacity"), ("Il2CppScheduleOne.ObjectScripts.MixingStation", "MaxMixQuantity") }; private MelonPreferences_Entry<int> limitEntry; private readonly Stopwatch clock = Stopwatch.StartNew(); private readonly Dictionary<long, int> originals = new Dictionary<long, int>(); private readonly HashSet<string> logged = new HashSet<string>(); private List<(Type type, PropertyInfo prop, object il2cppType)> resolved; private MethodInfo findAll; private long nextScan = -1L; private bool inGame; public override void OnInitializeMelon() { MelonPreferences_Category val = MelonPreferences.CreateCategory("BiggerStations", "Bigger Stations"); limitEntry = val.CreateEntry<int>("StationLimit", 100, "Limite das estações", "Capacidade do varal de secagem e quantidade máxima das estações de mistura (2 a 9999).", false, false, (ValueValidator)null, (string)null); } public override void OnSceneWasInitialized(int buildIndex, string sceneName) { inGame = sceneName == "Main"; nextScan = clock.ElapsedMilliseconds + 3000; } public override void OnUpdate() { if (nextScan < 0 || clock.ElapsedMilliseconds < nextScan) { return; } nextScan = (inGame ? (clock.ElapsedMilliseconds + 10000) : (-1)); try { Apply(); } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error("Falha ao aplicar: " + ex); nextScan = -1L; } } private void Apply() { if (!Resolve()) { nextScan = -1L; return; } int num = Math.Max(2, Math.Min(9999, limitEntry.Value)); foreach (var (type, propertyInfo, obj) in resolved) { if (!(findAll.Invoke(null, new object[1] { obj }) is IEnumerable enumerable)) { continue; } int num2 = 0; foreach (object item2 in enumerable) { Il2CppObjectBase val = (Il2CppObjectBase)((item2 is Il2CppObjectBase) ? item2 : null); if (val != null && !(val.Pointer == IntPtr.Zero)) { object obj2; try { obj2 = Activator.CreateInstance(type, val.Pointer); } catch { continue; } int num3 = (int)propertyInfo.GetValue(obj2); long key = val.Pointer.ToInt64(); if (!originals.TryGetValue(key, out var value)) { value = (originals[key] = num3); } if (value >= 2 && num3 != num) { propertyInfo.SetValue(obj2, num); num2++; } } } string item = $"{type.Name}.{propertyInfo.Name}={num}"; if (num2 > 0 && logged.Add(item)) { ((MelonBase)this).LoggerInstance.Msg($"{type.Name}.{propertyInfo.Name} -> {num}"); } } } private bool Resolve() { if (resolved != null) { return resolved.Count > 0; } resolved = new List<(Type, PropertyInfo, object)>(); findAll = FindType("UnityEngine.Resources")?.GetMethods(BindingFlags.Static | BindingFlags.Public).FirstOrDefault((MethodInfo m) => m.Name == "FindObjectsOfTypeAll" && !m.IsGenericMethod && m.GetParameters().Length == 1); 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(); if (findAll == null || methodInfo == null) { ((MelonBase)this).LoggerInstance.Error("API da Unity não encontrada."); return false; } (string, string)[] targets = Targets; for (int num = 0; num < targets.Length; num++) { (string, string) tuple = targets[num]; string item = tuple.Item1; string item2 = tuple.Item2; Type t = FindType(item); PropertyInfo propertyInfo = t?.GetProperty(item2, BindingFlags.Instance | BindingFlags.Public); if (t == null || propertyInfo == null || propertyInfo.PropertyType != typeof(int) || !propertyInfo.CanWrite) { ((MelonBase)this).LoggerInstance.Warning(item + "." + item2 + " não encontrado. Versão do jogo incompatível?"); continue; } object[] parameters = methodInfo.GetParameters().Select((ParameterInfo pi, int i) => (i != 0) ? ((!(pi.ParameterType == typeof(bool))) ? pi.DefaultValue : ((object)false)) : t).ToArray(); object obj = methodInfo.Invoke(null, parameters); if (obj != null) { resolved.Add((t, propertyInfo, obj)); } } return resolved.Count > 0; } 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; } } }