Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of PlantsAlwaysGrowIL2CPP v1.2.0
Mods/PlantsAlwaysGrowIL2CPP.dll
Decompiled a day agousing System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using HarmonyLib; using Il2Cpp; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.InteropTypes; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.EntityFramework; using Il2CppScheduleOne.GameTime; using Il2CppScheduleOne.Growing; using Il2CppScheduleOne.Lighting; using Il2CppSystem; using Il2CppSystem.Reflection; using MelonLoader; using Microsoft.CodeAnalysis; using PlantsAlwaysGrow; using UnityEngine; using UnityEngine.Events; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(PlantsAlwaysGrowMod), "PlantsAlwaysGrowMod", "1.2.0", "lasersquid", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("PlantsAlwaysGrowIL2CPP")] [assembly: AssemblyConfiguration("IL2CPP")] [assembly: AssemblyFileVersion("1.2.0.0")] [assembly: AssemblyInformationalVersion("1.2.0+2d3db6e364738c1f962df060763b5e2248b0e08e")] [assembly: AssemblyProduct("PlantsAlwaysGrowIL2CPP")] [assembly: AssemblyTitle("PlantsAlwaysGrowIL2CPP")] [assembly: NeutralResourcesLanguage("en-US")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.2.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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace PlantsAlwaysGrow { public class PlantsAlwaysGrowMod : MelonMod { private static bool _isPatchApplied; private static Harmony _harmonyInstance; public override void OnInitializeMelon() { ((MelonEventBase<LemonAction<int, string>>)(object)MelonEvents.OnSceneWasLoaded).Subscribe((LemonAction<int, string>)OnSceneLoaded, 0, false); Utils.Initialize(this); ((MelonBase)this).LoggerInstance.Msg("PlantsAlwaysGrow initialized."); } private void OnSceneLoaded(int buildIndex, string sceneName) { //IL_0024: Unknown result type (might be due to invalid IL or missing references) //IL_002e: Expected O, but got Unknown if (sceneName == "Main" && !_isPatchApplied) { try { _harmonyInstance = new Harmony("PlantsAlwaysGrowMod"); _harmonyInstance.PatchAll(); _isPatchApplied = true; } catch (Exception ex) { ((MelonBase)this).LoggerInstance.Error("Failed to patch mod: " + ex.Message); } } } } public static class Utils { public class UnityObjectComparer : IEqualityComparer<Object> { public bool Equals(Object a, Object b) { return a.GetInstanceID() == b.GetInstanceID(); } public int GetHashCode(Object item) { return item.GetInstanceID(); } } public static PlantsAlwaysGrowMod Mod; private static Assembly S1Assembly; public static void Initialize(PlantsAlwaysGrowMod mod) { Mod = mod; S1Assembly = AppDomain.CurrentDomain.GetAssemblies().First((Assembly a) => a.GetName().Name == "Assembly-CSharp"); } public static Treturn GetField<Ttarget, Treturn>(string fieldName, object target) where Treturn : class { return (Treturn)GetField<Ttarget>(fieldName, target); } public static object GetField<Ttarget>(string fieldName, object target) { return AccessTools.Property(typeof(Ttarget), fieldName).GetValue(target); } public static void SetField<Ttarget>(string fieldName, object target, object value) { AccessTools.Property(typeof(Ttarget), fieldName).SetValue(target, value); } public static Treturn GetProperty<Ttarget, Treturn>(string fieldName, object target) { return (Treturn)GetProperty<Ttarget>(fieldName, target); } public static object GetProperty<Ttarget>(string fieldName, object target) { return AccessTools.Property(typeof(Ttarget), fieldName).GetValue(target); } public static void SetProperty<Ttarget>(string fieldName, object target, object value) { AccessTools.Property(typeof(Ttarget), fieldName).SetValue(target, value); } public static Treturn CallMethod<Ttarget, Treturn>(string methodName, object target) { return (Treturn)CallMethod<Ttarget>(methodName, target, Array.Empty<object>()); } public static Treturn CallMethod<Ttarget, Treturn>(string methodName, object target, object[] args) { return (Treturn)CallMethod<Ttarget>(methodName, target, args); } public static Treturn CallMethod<Ttarget, Treturn>(string methodName, Type[] argTypes, object target, object[] args) { return (Treturn)CallMethod<Ttarget>(methodName, argTypes, target, args); } public static object CallMethod<Ttarget>(string methodName, object target) { return AccessTools.Method(typeof(Ttarget), methodName, (Type[])null, (Type[])null).Invoke(target, Array.Empty<object>()); } public static object CallMethod<Ttarget>(string methodName, object target, object[] args) { return AccessTools.Method(typeof(Ttarget), methodName, (Type[])null, (Type[])null).Invoke(target, args); } public static object CallMethod<Ttarget>(string methodName, Type[] argTypes, object target, object[] args) { return AccessTools.Method(typeof(Ttarget), methodName, argTypes, (Type[])null).Invoke(target, args); } public static T CastTo<T>(Il2CppObjectBase o) where T : Il2CppObjectBase { if (typeof(T).IsAssignableFrom(GetType(o))) { return (T)Activator.CreateInstance(typeof(T), o.Pointer); } return default(T); } public static bool Is<T>(Il2CppObjectBase o) where T : Il2CppObjectBase { return typeof(T).IsAssignableFrom(GetType(o)); } public static T ToInterface<T>(Il2CppObjectBase o) where T : Il2CppObjectBase { return (T)Activator.CreateInstance(typeof(T), o.Pointer); } public static Type GetType(Il2CppObjectBase o) { if (o == null) { return null; } string fullName = Il2CppType.TypeFromPointer(o.ObjectClass, "<unknown type>").FullName; return S1Assembly.GetType("Il2Cpp" + fullName); } public static UnityAction ToUnityAction(Action action) { return DelegateSupport.ConvertDelegate<UnityAction>((Delegate)action); } public static UnityAction<T> ToUnityAction<T>(Action<T> action) { return DelegateSupport.ConvertDelegate<UnityAction<T>>((Delegate)action); } public static Predicate<T> ToPredicate<T>(Func<T, bool> func) { return DelegateSupport.ConvertDelegate<Predicate<T>>((Delegate)func); } public static Action GetActionFromList(ActionList list, Func<Action, bool> predicate) { return list.list.Find(ToPredicate(predicate)); } public static void RemoveActionFromList(ActionList list, Action action) { list.Remove(action); } public static void AddActionToList(ActionList list, Action action) { list.Add(action); } public static void Log(string message) { ((MelonBase)Mod).LoggerInstance.Msg(message); } public static void Warn(string message) { ((MelonBase)Mod).LoggerInstance.Warning(message); } public static void PrintException(Exception e) { Warn("Exception: " + e.GetType().Name + " - " + e.Message); Warn("Source: " + e.Source); Warn(e.StackTrace ?? ""); if (e.InnerException != null) { Warn("Inner exception: " + e.InnerException.GetType().Name + " - " + e.InnerException.Message); Warn("Source: " + e.InnerException.Source); Warn(e.InnerException.StackTrace ?? ""); if (e.InnerException.InnerException != null) { Warn("Inner inner exception: " + e.InnerException.InnerException.GetType().Name + " - " + e.InnerException.InnerException.Message); Warn("Source: " + e.InnerException.InnerException.Source); Warn(e.InnerException.InnerException.StackTrace ?? ""); } } } public static bool OtherModIsLoaded(string modName) { List<MelonBase> list = new List<MelonBase>(MelonBase.RegisteredMelons); MelonBase val = list.Find((MelonBase m) => m.Info.Name == modName); return val != null; } } [HarmonyPatch] public static class AlwaysGrowPatches { [HarmonyPatch(typeof(Plant), "MinPass")] [HarmonyPostfix] public static void PlantMinPassPostfix(Plant __instance, int mins) { if (!(__instance.NormalizedGrowthProgress >= 1f) && NetworkSingleton<TimeManager>.Instance.IsEndOfDay) { float num = 1f / ((float)__instance.GrowthTime * 60f * (float)mins); num *= ((GrowContainer)__instance.Pot).GetTemperatureGrowthMultiplier(); num *= GetAverageLightExposure((GrowContainer)(object)__instance.Pot, out var growSpeedMultiplier); num *= __instance.Pot.GrowSpeedMultiplier; num *= growSpeedMultiplier; if (GameManager.IS_TUTORIAL) { num *= 0.3f; } if (((GrowContainer)__instance.Pot).NormalizedMoistureAmount <= 0f) { num *= 0f; } __instance.SetNormalizedGrowthProgress(__instance.NormalizedGrowthProgress + num); } } [HarmonyPatch(typeof(ShroomColony), "OnMinPass")] [HarmonyPostfix] public static void ShroomOnMinPassPostfix(ShroomColony __instance) { if (NetworkSingleton<TimeManager>.Instance.IsEndOfDay) { int num = (int)Utils.GetField<ShroomColony>("_growTime", __instance); float num2 = (float)Utils.CallMethod<ShroomColony>("GetCurrentGrowthRate", __instance); float num3 = num2 / ((float)num * 60f); Utils.CallMethod<ShroomColony>("ChangeGrowthPercentage", __instance, new object[1] { num3 }); } } private static float GetAverageLightExposure(GrowContainer container, out float growSpeedMultiplier) { growSpeedMultiplier = 1f; UsableLightSource field = Utils.GetField<GrowContainer, UsableLightSource>("_lightSourceOverride", container); if ((Object)(object)field != (Object)null) { return field.GrowSpeedMultiplier; } float num = 0f; float num2 = default(float); for (int i = 0; i < ((GridItem)container).CoordinatePairs.Count; i++) { num += ((GridItem)container).OwnerGrid.GetTile(((GridItem)container).CoordinatePairs[i].coord2).LightExposureNode.GetTotalExposure(ref num2); growSpeedMultiplier += num2; } growSpeedMultiplier /= ((GridItem)container).CoordinatePairs.Count; return num / (float)((GridItem)container).CoordinatePairs.Count; } [HarmonyPatch(typeof(GrowContainer), "InitializeGridItem")] [HarmonyPostfix] public static void InitializeGridItemPostfix(GrowContainer __instance) { TimeManager instance = NetworkSingleton<TimeManager>.Instance; Action actionFromList = Utils.GetActionFromList(instance.onMinutePass, (Action a) => ((MemberInfo)((Delegate)a).Method).Name == "OnMinPass" && ((Delegate)a).Target == __instance); Utils.RemoveActionFromList(instance.onMinutePass, actionFromList); Utils.AddActionToList(instance.onUncappedMinutePass, actionFromList); } [HarmonyPatch(typeof(GrowContainer), "Destroy")] [HarmonyPrefix] public static void DestroyPrefix(GrowContainer __instance) { TimeManager instance = NetworkSingleton<TimeManager>.Instance; Action actionFromList = Utils.GetActionFromList(instance.onUncappedMinutePass, (Action a) => ((MemberInfo)((Delegate)a).Method).Name == "OnMinPass" && ((Delegate)a).Target == __instance); Utils.RemoveActionFromList(instance.onUncappedMinutePass, actionFromList); Utils.AddActionToList(instance.onMinutePass, actionFromList); } } }