Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of Configurable Drying Rack Il2Cpp v1.0.1
Configurable_Drying_Rack_Il2Cpp.dll
Decompiled a day agousing System; using System.Diagnostics; using System.IO; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using ExampleMod; using HarmonyLib; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.ObjectScripts; using Il2CppScheduleOne.UI.Stations.Drying_rack; using MelonLoader; using MelonLoader.Preferences; using MelonLoader.Utils; using UnityEngine; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(global::ExampleMod.ExampleMod), "Configurable Drying Rack", "1.0", "Mr. Bones", null)] [assembly: MelonColor] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: MelonOptionalDependencies(new string[] { "FishNet.Runtime", "Il2CppFishNet.Runtime" })] [assembly: TargetFramework(".NETFramework,Version=v4.7.2", FrameworkDisplayName = ".NET Framework 4.7.2")] [assembly: AssemblyCompany("Configurable_Drying_Rack_Il2Cpp")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0")] [assembly: AssemblyProduct("Configurable_Drying_Rack_Il2Cpp")] [assembly: AssemblyTitle("Configurable_Drying_Rack_Il2Cpp")] [assembly: AssemblyVersion("1.0.0.0")] namespace ExampleMod; public static class BuildInfo { public const string Name = "Configurable Drying Rack"; public const string Description = ""; public const string Author = "Mr. Bones"; public const string Company = "Mr. Bones Workshop"; public const string Version = "1.0"; public const string DownloadLink = null; } public class ExampleMod : MelonMod { [HarmonyPatch(typeof(DryingRack), "Awake")] private static class DryingRack_Awake_Patch { private static void Postfix(DryingRack __instance) { __instance.ItemCapacity = cfgItemCapacity.Value; } } [HarmonyPatch(typeof(DryingRack), "MinPass")] private static class DryingRack_MinPass_Patch { private static bool IsServerLike() { try { Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); for (int i = 0; i < assemblies.Length; i++) { Type type = assemblies[i].GetType("FishNet.InstanceFinder"); if (!(type == null)) { PropertyInfo property = type.GetProperty("IsServer", BindingFlags.Static | BindingFlags.Public); if (!(property == null)) { object value = property.GetValue(null, null); if (value is bool) { return (bool)value; } break; } break; } } } catch { } return true; } private static bool Prefix(DryingRack __instance) { //IL_003f: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Invalid comparison between Unknown and I4 int value = cfgDryMinsPerTier.Value; foreach (DryingOperation item in __instance.DryingOperations.ToArray()) { int time = item.Time; item.Time = time + 1; if (item.Time < value) { continue; } if ((int)item.StartQuality >= 3) { if (IsServerLike() && __instance.GetOutputCapacityForOperation(item, (EQuality)4) >= item.Quantity) { __instance.TryEndOperation(__instance.DryingOperations.IndexOf(item), false, (EQuality)4, Random.Range(int.MinValue, int.MaxValue)); } } else { item.IncreaseQuality(); } } return false; } } [HarmonyPatch(typeof(DryingOperation), "GetQuality")] private static class DryingOperation_GetQuality_Patch { private static void Postfix(DryingOperation __instance, ref EQuality __result) { //IL_0013: Unknown result type (might be due to invalid IL or missing references) //IL_0019: Unknown result type (might be due to invalid IL or missing references) //IL_0021: Expected I4, but got Unknown int num = __instance.Time / cfgDryMinsPerTier.Value; int num2 = Mathf.Clamp(__instance.StartQuality + num, 0, 4); __result = (EQuality)num2; } } [HarmonyPatch(typeof(DryingOperationUI), "UpdatePosition")] private static class DryingOperationUI_UpdatePosition_Patch { private static void Postfix(DryingOperationUI __instance) { //IL_00be: Unknown result type (might be due to invalid IL or missing references) if (__instance.AssignedOperation == null) { MelonLogger.Warning("DryingOperationUI.UpdatePosition skipped: AssignedOperation is null"); return; } if ((Object)(object)__instance.Tooltip == (Object)null) { MelonLogger.Warning("DryingOperationUI.UpdatePosition skipped: Tooltip is null"); return; } if ((Object)(object)__instance.Rect == (Object)null) { MelonLogger.Warning("DryingOperationUI.UpdatePosition skipped: Rect is null"); return; } int value = cfgDryMinsPerTier.Value; int time = __instance.AssignedOperation.Time; float num = Mathf.Clamp01((float)time / (float)value); int num2 = Mathf.Clamp(value - time, 0, value); int num3 = num2 / 60; int num4 = num2 % 60; __instance.Tooltip.text = $"{num3}h {num4}m until next tier"; float num5 = -62.5f; float num6 = 0f - num5; __instance.Rect.anchoredPosition = new Vector2(Mathf.Lerp(num5, num6, num), 0f); } } private static readonly MelonPreferences_Category cfgCategory; private static readonly MelonPreferences_Entry<int> cfgDryMinsPerTier; private static readonly MelonPreferences_Entry<int> cfgItemCapacity; static ExampleMod() { cfgCategory = MelonPreferences.CreateCategory("ConfigurableDryingRack", "Configurable Drying Rack"); cfgDryMinsPerTier = cfgCategory.CreateEntry<int>("DryMinsPerTier", 720, (string)null, "Minutes required per tier", false, false, (ValueValidator)null, (string)null); cfgItemCapacity = cfgCategory.CreateEntry<int>("ItemCapacity", 20, (string)null, "Slots available on the rack", false, false, (ValueValidator)null, (string)null); cfgCategory.SetFilePath(Path.Combine(MelonEnvironment.UserDataDirectory, "Configurable Drying Rack.cfg")); } public override void OnInitializeMelon() { MelonPreferences.Save(); } }