Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of SuperGrow v1.3.1
SuperGrow_Il2Cpp.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using HarmonyLib; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.Equipping; using Il2CppScheduleOne.Growing; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.ObjectScripts; using Il2CppScheduleOne.PlayerScripts; using Il2CppScheduleOne.PlayerTasks; using Il2CppScheduleOne.PlayerTasks.Tasks; using Il2CppScheduleOne.StationFramework; using Il2CppScheduleOne.Storage; using Il2CppScheduleOne.Trash; using Il2CppScheduleOne.UI.Stations; using Il2CppSystem.Collections.Generic; using Il2CppTMPro; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using SuperGrow; using SuperGrow.Features; using SuperGrow.Patches; using SuperGrow.Utils; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(Core), "SuperGrow", "1.3.0", "HazDS", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("SuperGrow_Il2Cpp")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+210d764bdf4017213cdf984dcb70d397bf5d2d97")] [assembly: AssemblyProduct("SuperGrow_Il2Cpp")] [assembly: AssemblyTitle("SuperGrow_Il2Cpp")] [assembly: NeutralResourcesLanguage("en-US")] [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 SuperGrow { internal static class SuperGrowSettings { private static bool _initialized; private static MelonPreferences_Category? _prefsCategory; public static MelonPreferences_Entry<int> PgrRequired { get; private set; } public static MelonPreferences_Entry<int> SpeedGrowRequired { get; private set; } public static MelonPreferences_Entry<int> FertilizerRequired { get; private set; } public static MelonPreferences_Entry<int> OutputQuantity { get; private set; } public static MelonPreferences_Entry<float> YieldMultiplier { get; private set; } public static MelonPreferences_Entry<float> InstantGrowth { get; private set; } public static MelonPreferences_Entry<float> QualityChange { get; private set; } public static void Initialize() { if (!_initialized) { _prefsCategory = MelonPreferences.CreateCategory("SuperGrow", "SuperGrow Settings"); PgrRequired = _prefsCategory.CreateEntry<int>("PgrRequired", 1, "PGR Required", "Amount of PGR needed per craft", false, false, (ValueValidator)null, (string)null); SpeedGrowRequired = _prefsCategory.CreateEntry<int>("SpeedGrowRequired", 1, "Speed Grow Required", "Amount of Speed Grow needed per craft", false, false, (ValueValidator)null, (string)null); FertilizerRequired = _prefsCategory.CreateEntry<int>("FertilizerRequired", 1, "Fertilizer Required", "Amount of Fertilizer needed per craft", false, false, (ValueValidator)null, (string)null); OutputQuantity = _prefsCategory.CreateEntry<int>("OutputQuantity", 3, "Output Quantity", "Amount of SuperGrow produced per craft", false, false, (ValueValidator)null, (string)null); YieldMultiplier = _prefsCategory.CreateEntry<float>("YieldMultiplier", 1.5f, "Yield Multiplier", "Yield multiplier applied to plants (1.5 = 50% more yield)", false, false, (ValueValidator)null, (string)null); InstantGrowth = _prefsCategory.CreateEntry<float>("InstantGrowth", 0.5f, "Instant Growth", "Instant growth progress (0.5 = 50% instant growth)", false, false, (ValueValidator)null, (string)null); QualityChange = _prefsCategory.CreateEntry<float>("QualityChange", 1f, "Quality Change", "Quality modifier applied to plants", false, false, (ValueValidator)null, (string)null); Clamp(PgrRequired, 1, 10); Clamp(SpeedGrowRequired, 1, 10); Clamp(FertilizerRequired, 1, 10); Clamp(OutputQuantity, 1, 10); Clamp(YieldMultiplier, 0.1f, 10f); Clamp(InstantGrowth, 0f, 1f); Clamp(QualityChange, -1f, 1f); _initialized = true; } } private static void Clamp(MelonPreferences_Entry<int> entry, int min, int max) { if (entry.Value < min) { entry.Value = min; } if (entry.Value > max) { entry.Value = max; } } private static void Clamp(MelonPreferences_Entry<float> entry, float min, float max) { if (entry.Value < min) { entry.Value = min; } if (entry.Value > max) { entry.Value = max; } } } public class Core : MelonMod { private bool _itemsInitialized; private int _nextInitAttemptTick; private const int InitAttemptIntervalMs = 250; public static Core Instance { get; private set; } public override void OnInitializeMelon() { Instance = this; SuperGrowSettings.Initialize(); MelonLogger.Msg("[SuperGrow v1.3.0] Initialized."); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { if (sceneName == "Menu") { _itemsInitialized = false; _nextInitAttemptTick = 0; ChemistryStationPatches.Reset(); } } public override void OnUpdate() { if (_itemsInitialized && (Object)(object)Registry.GetItem("supergrow") != (Object)null) { return; } if ((Object)(object)Registry.GetItem("supergrow") != (Object)null) { ChemistryStationPatches.EnsureAdditiveStationItemPrefabs(); _itemsInitialized = true; } else if (ShouldAttemptInitNow()) { _itemsInitialized = false; if (SuperGrowWorldState.IsRegistryReady()) { SuperGrowCreator.CreateSuperGrowItem(); ChemistryStationPatches.EnsureAdditiveStationItemPrefabs(); _itemsInitialized = (Object)(object)Registry.GetItem("supergrow") != (Object)null; } } } private bool ShouldAttemptInitNow() { int tickCount = Environment.TickCount; if (tickCount - _nextInitAttemptTick < 0) { return false; } _nextInitAttemptTick = tickCount + 250; return true; } } internal static class SuperGrowAssets { private const string IconResourceName = "SuperGrow.Assets.SuperGrow_Icon.png"; private const string LabelResourceName = "SuperGrow.Assets.SuperGrow_Label.png"; private static Sprite? _icon; private static Texture2D? _labelTexture; private static bool _loggedIconLoadException; private static bool _loggedLabelLoadException; private static bool _loggedImageLoadException; public static Sprite? GetIconSprite() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_icon != (Object)null) { return _icon; } try { byte[] array = LoadEmbeddedResourceBytes("SuperGrow.Assets.SuperGrow_Icon.png"); if (array == null) { return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!TryLoadImage(val, array)) { MelonLogger.Warning("Failed to decode SuperGrow.Assets.SuperGrow_Icon.png"); return null; } ((Object)val).name = "SuperGrow_Icon"; _icon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); return _icon; } catch (Exception ex) { if (!_loggedIconLoadException) { _loggedIconLoadException = true; MelonLogger.Warning("Failed to load icon: " + ex.Message); MelonLogger.Warning(ex.StackTrace ?? "<no stack trace>"); } return null; } } public static Texture2D? GetLabelTexture() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown if ((Object)(object)_labelTexture != (Object)null) { return _labelTexture; } try { byte[] array = LoadEmbeddedResourceBytes("SuperGrow.Assets.SuperGrow_Label.png"); if (array == null) { return null; } _labelTexture = new Texture2D(2, 2, (TextureFormat)4, false); if (!TryLoadImage(_labelTexture, array)) { MelonLogger.Warning("Failed to decode SuperGrow.Assets.SuperGrow_Label.png"); _labelTexture = null; return null; } ((Object)_labelTexture).name = "SuperGrow_Label"; return _labelTexture; } catch (Exception ex) { if (!_loggedLabelLoadException) { _loggedLabelLoadException = true; MelonLogger.Error("Failed to load SuperGrow label texture: " + ex.Message); MelonLogger.Error(ex.StackTrace ?? "<no stack trace>"); } _labelTexture = null; return null; } } private static byte[]? LoadEmbeddedResourceBytes(string resourceName) { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName); if (stream == null) { MelonLogger.Warning("Could not find embedded resource: " + resourceName); return null; } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); return memoryStream.ToArray(); } private static bool TryLoadImage(Texture2D texture, byte[] bytes) { try { Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule") ?? typeof(Texture2D).Assembly.GetType("UnityEngine.ImageConversion"); if (type == null) { return false; } MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public); bool flag = default(bool); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != "LoadImage") { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if ((parameters.Length != 2 && parameters.Length != 3) || parameters[0].ParameterType != typeof(Texture2D)) { continue; } Type parameterType = parameters[1].ParameterType; object obj; if (parameterType == typeof(byte[])) { obj = bytes; } else { if (!parameterType.IsGenericType || !(parameterType.GetGenericTypeDefinition() == typeof(Il2CppStructArray<>))) { continue; } Il2CppStructArray<byte> val = new Il2CppStructArray<byte>((long)bytes.Length); for (int j = 0; j < bytes.Length; j++) { ((Il2CppArrayBase<byte>)(object)val)[j] = bytes[j]; } obj = val; } object obj2 = ((parameters.Length != 3) ? methodInfo.Invoke(null, new object[2] { texture, obj }) : methodInfo.Invoke(null, new object[3] { texture, obj, false })); int num; if (obj2 is bool) { flag = (bool)obj2; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } return false; } catch (Exception ex) { if (!_loggedImageLoadException) { _loggedImageLoadException = true; MelonLogger.Warning("Failed to decode embedded image bytes via ImageConversion.LoadImage: " + ex.Message); MelonLogger.Warning(ex.StackTrace ?? "<no stack trace>"); } return false; } } } internal static class SuperGrowWorldState { private static bool _loggedReady; private static bool _ready; private static bool _loggedRegistryReadyException; public static bool IsRegistryReady() { try { if (_ready) { return true; } ItemDefinition item = Registry.GetItem("pgr"); AdditiveDefinition obj = ((item != null) ? ((Il2CppObjectBase)item).TryCast<AdditiveDefinition>() : null); ItemDefinition item2 = Registry.GetItem("speedgrow"); AdditiveDefinition val = ((item2 != null) ? ((Il2CppObjectBase)item2).TryCast<AdditiveDefinition>() : null); ItemDefinition item3 = Registry.GetItem("fertilizer"); AdditiveDefinition val2 = ((item3 != null) ? ((Il2CppObjectBase)item3).TryCast<AdditiveDefinition>() : null); if ((Object)(object)obj == (Object)null && (Object)(object)val == (Object)null && (Object)(object)val2 == (Object)null) { return false; } _ready = true; if (!_loggedReady) { _loggedReady = true; } return true; } catch (Exception ex) { if (!_loggedRegistryReadyException) { _loggedRegistryReadyException = true; MelonLogger.Warning("Registry readiness check failed: " + ex.Message); MelonLogger.Warning(ex.StackTrace ?? "<no stack trace>"); } return false; } } } } namespace SuperGrow.Utils { public static class Constants { public static class Game { public const string GAME_STUDIO = "TVGS"; public const string GAME_NAME = "Schedule I"; } public static class Additives { public const string PGR = "pgr"; public const string SPEED_GROW = "speedgrow"; public const string FERTILIZER = "fertilizer"; } public static class ItemIds { public const string SUPER_GROW = "supergrow"; } public static class DefaultEffects { public const float YIELD_MULTIPLIER = 1.5f; public const float INSTANT_GROWTH = 0.5f; public const float QUALITY_CHANGE = 1f; } public const string MOD_NAME = "SuperGrow"; public const string MOD_VERSION = "1.3.0"; public const string MOD_AUTHOR = "HazDS"; public const string PREFERENCES_CATEGORY = "SuperGrow"; } internal static class SuperGrowVisuals { internal static readonly Color PourColor = new Color(0.4f, 0.2f, 0.6f, 1f); internal static readonly Color LidTint = new Color(0.6f, 0.4f, 0.8f, 1f); internal static void ApplySuperGrowMaterialsToRenderers(Renderer[]? renderers) { //IL_01c2: Unknown result type (might be due to invalid IL or missing references) //IL_01e1: Unknown result type (might be due to invalid IL or missing references) //IL_0200: Unknown result type (might be due to invalid IL or missing references) if (renderers == null) { return; } Texture2D labelTexture = SuperGrowAssets.GetLabelTexture(); if ((Object)(object)labelTexture == (Object)null) { MelonLogger.Warning("SuperGrow label texture is null, cannot apply"); return; } try { foreach (Renderer val in renderers) { if ((Object)(object)val == (Object)null) { continue; } string text = ((Object)val).name.ToLowerInvariant(); bool flag = text.Contains("label"); if (!flag) { foreach (Material item in (Il2CppArrayBase<Material>)(object)val.sharedMaterials) { if ((Object)(object)item != (Object)null && ((Object)item).name.ToLowerInvariant().Contains("label")) { flag = true; break; } } } bool flag2 = text.Contains("lid"); if (!flag2) { foreach (Material item2 in (Il2CppArrayBase<Material>)(object)val.sharedMaterials) { if ((Object)(object)item2 != (Object)null && ((Object)item2).name.ToLowerInvariant().Contains("lid")) { flag2 = true; break; } } } if (flag) { Il2CppReferenceArray<Material> materials = val.materials; for (int j = 0; j < ((Il2CppArrayBase<Material>)(object)materials).Length; j++) { Material val2 = ((Il2CppArrayBase<Material>)(object)materials)[j]; if (!((Object)(object)val2 == (Object)null)) { val2.mainTexture = (Texture)(object)labelTexture; if (val2.HasProperty("_BaseMap")) { val2.SetTexture("_BaseMap", (Texture)(object)labelTexture); } if (val2.HasProperty("_MainTex")) { val2.SetTexture("_MainTex", (Texture)(object)labelTexture); } } } val.materials = materials; } else { if (!flag2) { continue; } Il2CppReferenceArray<Material> materials2 = val.materials; for (int k = 0; k < ((Il2CppArrayBase<Material>)(object)materials2).Length; k++) { Material val3 = ((Il2CppArrayBase<Material>)(object)materials2)[k]; if (!((Object)(object)val3 == (Object)null)) { val3.color = LidTint; if (val3.HasProperty("_BaseColor")) { val3.SetColor("_BaseColor", LidTint); } if (val3.HasProperty("_Color")) { val3.SetColor("_Color", LidTint); } } } val.materials = materials2; } } } catch (Exception ex) { MelonLogger.Error("Failed to apply SuperGrow materials: " + ex.Message); MelonLogger.Error(ex.StackTrace); } } } } namespace SuperGrow.Patches { [HarmonyPatch] internal static class ChemistryStationPatches { private readonly struct PendingTrashReskin { public string TrashId { get; } public string AdditiveId { get; } public PendingTrashReskin(string trashId, string additiveId) { TrashId = trashId; AdditiveId = additiveId; } } [CompilerGenerated] private sealed class <DelayedChemistryIngredientAudit>d__42 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedChemistryIngredientAudit>d__42(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.4f); <>1__state = 2; return true; case 2: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 3; return true; case 3: <>1__state = -1; 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 StationRecipe? _superGrowRecipe; private static bool _additivesPatched; private static bool _loggedMissingStationItemTemplate; private static bool _loggedRegistryStart; private static bool _loggedRecipeNotReady; private static int _superGrowBeginAuditUntilTick; private static int _superGrowBeginAuditSeq; private static ChemistryStation? _superGrowBeginStation; private static int _superGrowBeginStationSeq; private static string? _lastSelectedRecipeProductId; private static string? _lastSelectedRecipeTitle; private static string? _lastSelectedRecipeId; private static int _lastSelectedAtTick; private const string PgrBottleTrashId = "supergrow_pgr_bottle"; private const string SpeedGrowBottleTrashId = "supergrow_speedgrow_bottle"; private const string FertilizerBottleTrashId = "supergrow_fertilizer_bottle"; private const string SuperGrowBottleTrashId = "supergrow_bottle"; private static GameObject? _prefabCacheRoot; private static bool _baseStationItemPrefabsEnsured; private static readonly Dictionary<string, StationItem> _stationItemPrefabByAdditiveId = new Dictionary<string, StationItem>(); private static int _il2cppTrashPrefabsEnsuredForManagerId; private static readonly Dictionary<string, TrashItem> _il2cppBottleTrashPrefabByAdditiveId = new Dictionary<string, TrashItem>(StringComparer.OrdinalIgnoreCase); private static bool _loggedIl2CppTrashPrefabInjectionException; private static bool _loggedIl2CppTrashPrefabEnsureException; private static int _pendingStationTrashReskinExpireTick; private static readonly List<PendingTrashReskin> _pendingStationTrashReskins = new List<PendingTrashReskin>(); private static readonly Dictionary<string, GameObject> _pourablePrefabs = new Dictionary<string, GameObject>(); private static readonly Dictionary<string, Color> _additiveColors = new Dictionary<string, Color> { { "pgr", new Color(1f, 0.506f, 0.506f, 1f) }, { "speedgrow", new Color(0.506f, 0.812f, 1f, 1f) }, { "fertilizer", new Color(0.639f, 1f, 0.506f, 1f) }, { "supergrow", SuperGrowVisuals.PourColor } }; private const float LiquidScale = 0.65f; public static void Reset() { _superGrowRecipe = null; _additivesPatched = false; _loggedMissingStationItemTemplate = false; _loggedRegistryStart = false; _loggedRecipeNotReady = false; _baseStationItemPrefabsEnsured = false; _il2cppTrashPrefabsEnsuredForManagerId = 0; } private static Transform GetOrCreatePrefabCacheRoot() { //IL_001d: Unknown result type (might be due to invalid IL or missing references) //IL_0027: Expected O, but got Unknown if ((Object)(object)_prefabCacheRoot != (Object)null) { return _prefabCacheRoot.transform; } _prefabCacheRoot = new GameObject("SuperGrow_PrefabCache"); Object.DontDestroyOnLoad((Object)(object)_prefabCacheRoot); _prefabCacheRoot.SetActive(false); return _prefabCacheRoot.transform; } private static bool TryGetBottleTrashId(string additiveId, out string trashId) { trashId = null; if (string.Equals(additiveId, "pgr", StringComparison.OrdinalIgnoreCase)) { trashId = "supergrow_pgr_bottle"; return true; } if (string.Equals(additiveId, "speedgrow", StringComparison.OrdinalIgnoreCase)) { trashId = "supergrow_speedgrow_bottle"; return true; } if (string.Equals(additiveId, "fertilizer", StringComparison.OrdinalIgnoreCase)) { trashId = "supergrow_fertilizer_bottle"; return true; } return false; } private static void EnsureIl2CppBottleTrashPrefabsInjected(TrashManager manager) { TrashManager manager2 = manager; if ((Object)(object)manager2 == (Object)null) { return; } int instanceID = ((Object)manager2).GetInstanceID(); if (instanceID != 0 && instanceID == _il2cppTrashPrefabsEnsuredForManagerId) { return; } try { CachePourablePrefab("pgr", "growing/pgr/PGR_Pourable"); CachePourablePrefab("speedgrow", "growing/speedgrow/SpeedGrow_Pourable"); CachePourablePrefab("fertilizer", "growing/fertilizer/Fertilizer_Pourable"); TrashItem baseTrash = manager2.GetTrashPrefab("acid"); TrashItem pgrTrash = manager2.GetTrashPrefab("pgr"); if ((Object)(object)baseTrash == (Object)null || (Object)(object)((Component)baseTrash).gameObject == (Object)null) { return; } List<TrashItem> additions = new List<TrashItem>(); Ensure("pgr", "supergrow_pgr_bottle"); Ensure("speedgrow", "supergrow_speedgrow_bottle"); Ensure("fertilizer", "supergrow_fertilizer_bottle"); Ensure("supergrow", "supergrow_bottle"); if (additions.Count == 0) { _il2cppTrashPrefabsEnsuredForManagerId = instanceID; return; } Il2CppReferenceArray<TrashItem> trashPrefabs = manager2.TrashPrefabs; int num = ((Il2CppArrayBase<TrashItem>)(object)trashPrefabs)?.Length ?? 0; TrashItem[] array = (TrashItem[])(object)new TrashItem[num + additions.Count]; for (int i = 0; i < num; i++) { array[i] = ((Il2CppArrayBase<TrashItem>)(object)trashPrefabs)[i]; } for (int j = 0; j < additions.Count; j++) { array[num + j] = additions[j]; } manager2.TrashPrefabs = new Il2CppReferenceArray<TrashItem>(array); _il2cppTrashPrefabsEnsuredForManagerId = instanceID; void Ensure(string additiveId, string newId) { try { if (!((Object)(object)manager2.GetTrashPrefab(newId) != (Object)null)) { if (_il2cppBottleTrashPrefabByAdditiveId.TryGetValue(additiveId, out TrashItem value) && (Object)(object)value != (Object)null) { value.ID = newId; additions.Add(value); } else { Transform orCreatePrefabCacheRoot = GetOrCreatePrefabCacheRoot(); GameObject val = ((string.Equals(additiveId, "supergrow", StringComparison.OrdinalIgnoreCase) && (Object)(object)pgrTrash != (Object)null && (Object)(object)((Component)pgrTrash).gameObject != (Object)null) ? ((Component)pgrTrash).gameObject : ((Component)baseTrash).gameObject); GameObject val2 = Object.Instantiate<GameObject>(val); ((Object)val2).name = "SuperGrow_" + additiveId + "_TrashPrefab"; val2.SetActive(val.activeSelf); val2.transform.SetParent(orCreatePrefabCacheRoot, false); Object.DontDestroyOnLoad((Object)(object)val2); TrashItem component = val2.GetComponent<TrashItem>(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val2); } else { component.ID = newId; SwapTrashItemVisualsById(additiveId, component); _il2cppBottleTrashPrefabByAdditiveId[additiveId] = component; additions.Add(component); } } } } catch (Exception ex2) { if (!_loggedIl2CppTrashPrefabEnsureException) { _loggedIl2CppTrashPrefabEnsureException = true; MelonLogger.Warning("Failed to create SuperGrow trash prefab for '" + additiveId + "' (IL2CPP): " + ex2.Message); MelonLogger.Warning(ex2.StackTrace ?? "<no stack trace>"); } } } } catch (Exception ex) { if (!_loggedIl2CppTrashPrefabInjectionException) { _loggedIl2CppTrashPrefabInjectionException = true; MelonLogger.Warning("Failed to inject SuperGrow trash prefabs (IL2CPP): " + ex.Message); MelonLogger.Warning(ex.StackTrace ?? "<no stack trace>"); } } } private static void TryAssignIl2CppBottleTrashPrefab(string additiveId, StationItem stationItem) { if ((Object)(object)stationItem == (Object)null || !TryGetBottleTrashId(additiveId, out string trashId)) { return; } try { TrashManager val = Object.FindObjectOfType<TrashManager>(); if ((Object)(object)val == (Object)null) { return; } EnsureIl2CppBottleTrashPrefabsInjected(val); if (_il2cppBottleTrashPrefabByAdditiveId.TryGetValue(additiveId, out TrashItem value) && (Object)(object)value != (Object)null) { stationItem.TrashPrefab = value; return; } TrashItem trashPrefab = val.GetTrashPrefab(trashId); if ((Object)(object)trashPrefab != (Object)null) { stationItem.TrashPrefab = trashPrefab; } } catch { } } private static void ApplyIl2CppBottleTrashPrefabsToCachedStationItems(TrashManager manager) { if ((Object)(object)manager == (Object)null) { return; } try { EnsureIl2CppBottleTrashPrefabsInjected(manager); string[] array = new string[3] { "pgr", "speedgrow", "fertilizer" }; foreach (string text in array) { if (_stationItemPrefabByAdditiveId.TryGetValue(text, out StationItem value) && (Object)(object)value != (Object)null) { TryAssignIl2CppBottleTrashPrefab(text, value); } } } catch { } } public static bool EnsureAdditiveStationItemPrefabs() { if (!TryGetStationItemTemplate(out StationItem templateStationItem)) { return false; } CachePourablePrefab("pgr", "growing/pgr/PGR_Pourable"); CachePourablePrefab("speedgrow", "growing/speedgrow/SpeedGrow_Pourable"); CachePourablePrefab("fertilizer", "growing/fertilizer/Fertilizer_Pourable"); TrashManager val = Object.FindObjectOfType<TrashManager>(); if ((Object)(object)val != (Object)null) { EnsureIl2CppBottleTrashPrefabsInjected(val); } if (!_baseStationItemPrefabsEnsured) { _baseStationItemPrefabsEnsured = true; EnsureStationItemPrefabForAdditive("pgr", templateStationItem, overrideIfPresent: true); EnsureStationItemPrefabForAdditive("speedgrow", templateStationItem, overrideIfPresent: true); EnsureStationItemPrefabForAdditive("fertilizer", templateStationItem, overrideIfPresent: true); } EnsureStationItemPrefabForAdditive("supergrow", templateStationItem, overrideIfPresent: true); return true; } private static void EnsureStationItemPrefabForAdditive(string additiveId, StationItem templateStationItem, bool overrideIfPresent) { ItemDefinition item = Registry.GetItem(additiveId); StorableItemDefinition val = ((item != null) ? ((Il2CppObjectBase)item).TryCast<StorableItemDefinition>() : null); if ((Object)(object)val == (Object)null || (!overrideIfPresent && (Object)(object)val.StationItem != (Object)null)) { return; } if (_stationItemPrefabByAdditiveId.TryGetValue(additiveId, out StationItem value) && (Object)(object)value != (Object)null) { val.StationItem = value; TryAssignIl2CppBottleTrashPrefab(additiveId, value); return; } Transform orCreatePrefabCacheRoot = GetOrCreatePrefabCacheRoot(); GameObject val2 = Object.Instantiate<GameObject>(((Component)templateStationItem).gameObject); ((Object)val2).name = "SuperGrow_StationItemPrefab_" + additiveId; val2.SetActive(true); val2.transform.SetParent(orCreatePrefabCacheRoot, false); Object.DontDestroyOnLoad((Object)(object)val2); StationItem component = val2.GetComponent<StationItem>(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val2); return; } TryAssignIl2CppBottleTrashPrefab(additiveId, component); _stationItemPrefabByAdditiveId[additiveId] = component; val.StationItem = component; SwapStationItemVisualsById(additiveId, component); } [HarmonyPatch(typeof(TrashManager), "Start")] [HarmonyPostfix] private static void TrashManager_Start_Postfix_Il2Cpp(TrashManager __instance) { EnsureIl2CppBottleTrashPrefabsInjected(__instance); ApplyIl2CppBottleTrashPrefabsToCachedStationItems(__instance); } [HarmonyPatch(typeof(ChemistryStationCanvas), "Awake")] [HarmonyPrefix] private static void ChemistryStationCanvas_Awake_Prefix(ChemistryStationCanvas __instance) { try { if ((Object)(object)__instance == (Object)null) { return; } SuperGrowCreator.CreateSuperGrowItem(); if ((Object)(object)_superGrowRecipe == (Object)null) { CreateSuperGrowRecipe(); } if ((Object)(object)_superGrowRecipe == (Object)null) { if (!_loggedRecipeNotReady) { _loggedRecipeNotReady = true; MelonLogger.Warning("SuperGrow recipe is null; cannot add to chemistry station yet"); } return; } List<StationRecipe> recipes = __instance.Recipes; if (recipes == null) { if (!_loggedRecipeNotReady) { _loggedRecipeNotReady = true; MelonLogger.Warning("ChemistryStationCanvas.Recipes is null; cannot add SuperGrow recipe"); } } else if (!recipes.Contains(_superGrowRecipe)) { recipes.Add(_superGrowRecipe); } } catch (Exception ex) { MelonLogger.Error("Failed to add SuperGrow recipe: " + ex.Message); MelonLogger.Error(ex.StackTrace ?? "<no stack trace>"); } } [HarmonyPatch(typeof(ChemistryStationCanvas), "Awake")] [HarmonyPostfix] private static void ChemistryStationCanvas_Awake_Postfix(ChemistryStationCanvas __instance) { } [HarmonyPatch(typeof(ChemistryStationCanvas), "Start")] [HarmonyPrefix] private static void ChemistryStationCanvas_Start_Prefix(ChemistryStationCanvas __instance) { try { if (!((Object)(object)__instance == (Object)null)) { SetupAdditiveStationItems(); } } catch (Exception ex) { MelonLogger.Error("Failed to add SuperGrow recipe: " + ex.Message); MelonLogger.Error(ex.StackTrace ?? "<no stack trace>"); } } [HarmonyPatch(typeof(ChemistryStationCanvas), "Start")] [HarmonyPostfix] private static void ChemistryStationCanvas_Start_Postfix(ChemistryStationCanvas __instance) { } [HarmonyPatch(typeof(ChemistryStationCanvas), "Open")] [HarmonyPrefix] private static void ChemistryStationCanvas_Open_PrefixAudit(ChemistryStationCanvas __instance, ChemistryStation station) { } [HarmonyPatch(typeof(ChemistryStationCanvas), "SetSelectedRecipe")] [HarmonyPrefix] private static void ChemistryStationCanvas_SetSelectedRecipe_Prefix(ChemistryStationCanvas __instance, StationRecipeEntry entry) { try { StationRecipe val = ((entry != null) ? entry.Recipe : null); string text = SafeGetProductId(val); if (!(text == "<null>") && !(text == "<error>")) { _lastSelectedRecipeProductId = text; _lastSelectedRecipeTitle = SafeGetRecipeEntryTitle(entry); _lastSelectedRecipeId = (((Object)(object)val == (Object)null) ? "<null>" : SafeGetStationRecipeId(val)); _lastSelectedAtTick = Environment.TickCount; } } catch { } } [HarmonyPatch(typeof(ChemistryStationCanvas), "BeginButtonPressed")] [HarmonyPrefix] private static void ChemistryStationCanvas_BeginButtonPressed_Prefix(ChemistryStationCanvas __instance) { try { if (!((Object)(object)__instance == (Object)null)) { StationRecipeEntry? obj = TryGetSelectedRecipeEntry(__instance); string text = SafeGetProductId((obj != null) ? obj.Recipe : null); if (text == "<null>" || text == "<error>") { text = _lastSelectedRecipeProductId ?? text; } if (!(text != "supergrow")) { _superGrowBeginAuditSeq++; _superGrowBeginAuditUntilTick = Environment.TickCount + 10000; _superGrowBeginStation = __instance.ChemistryStation; _superGrowBeginStationSeq = _superGrowBeginAuditSeq; _ = _superGrowBeginAuditSeq; } } } catch (Exception ex) { MelonLogger.Error("SuperGrow Begin audit failed (Prefix): " + ex.Message); MelonLogger.Error(ex.StackTrace ?? "<no stack trace>"); } } [HarmonyPatch(typeof(ChemistryStationCanvas), "BeginButtonPressed")] [HarmonyPostfix] private static void ChemistryStationCanvas_BeginButtonPressed_Postfix(ChemistryStationCanvas __instance) { try { if (!((Object)(object)__instance == (Object)null) && !TickExpired(_superGrowBeginAuditUntilTick)) { int superGrowBeginAuditSeq = _superGrowBeginAuditSeq; ChemistryStation val = __instance.ChemistryStation; if ((Object)(object)val == (Object)null && _superGrowBeginStationSeq == superGrowBeginAuditSeq) { val = _superGrowBeginStation; } _ = (Object)(object)val != (Object)null; } } catch (Exception ex) { MelonLogger.Error("SuperGrow Begin audit failed (Postfix): " + ex.Message); MelonLogger.Error(ex.StackTrace ?? "<no stack trace>"); } } private static bool TickExpired(int untilTick) { return Environment.TickCount - untilTick >= 0; } [IteratorStateMachine(typeof(<DelayedChemistryIngredientAudit>d__42))] private static IEnumerator DelayedChemistryIngredientAudit(int seq, ChemistryStation station) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayedChemistryIngredientAudit>d__42(0); } private static StationRecipeEntry? TryGetSelectedRecipeEntry(ChemistryStationCanvas canvas) { try { Type typeFromHandle = typeof(ChemistryStationCanvas); FieldInfo fieldInfo = AccessTools.Field(typeFromHandle, "selectedRecipe"); if (fieldInfo != null) { object? value = fieldInfo.GetValue(canvas); return (StationRecipeEntry?)((value is StationRecipeEntry) ? value : null); } FieldInfo[] fields = typeFromHandle.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo2 in fields) { if (!(fieldInfo2.FieldType != typeof(StationRecipeEntry)) && !(fieldInfo2.Name == "RecipeEntryPrefab") && !(fieldInfo2.Name == "InProgressRecipeEntry")) { object? value2 = fieldInfo2.GetValue(canvas); StationRecipeEntry val = (StationRecipeEntry)((value2 is StationRecipeEntry) ? value2 : null); if ((Object)(object)((val != null) ? val.Recipe : null) != (Object)null) { return val; } } } } catch { } return null; } private static string SafeGetRecipeEntryTitle(StationRecipeEntry? entry) { try { return ((Object)(object)((entry != null) ? entry.TitleLabel : null) == (Object)null) ? "<null>" : (((TMP_Text)entry.TitleLabel).text ?? "<null>"); } catch { return "<error>"; } } private static bool SafeGetBeginInteractable(ChemistryStationCanvas canvas) { try { return (Object)(object)canvas.BeginButton != (Object)null && ((Selectable)canvas.BeginButton).interactable; } catch { return false; } } private static string SafeGetProductId(StationRecipe? recipe) { try { object obj; if (recipe == null) { obj = null; } else { ItemQuantity product = recipe.Product; if (product == null) { obj = null; } else { ItemDefinition item = product.Item; obj = ((item != null) ? item.ID : null); } } if (obj == null) { obj = "<null>"; } return (string)obj; } catch { return "<error>"; } } private static string SafeGetStationRecipeId(StationRecipe recipe) { try { return recipe.RecipeID ?? "<null>"; } catch { return "<error>"; } } private static void CreateSuperGrowRecipe() { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Expected O, but got Unknown //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Expected O, but got Unknown //IL_01a2: Unknown result type (might be due to invalid IL or missing references) ItemDefinition item = Registry.GetItem("pgr"); ItemDefinition item2 = Registry.GetItem("speedgrow"); ItemDefinition item3 = Registry.GetItem("fertilizer"); ItemDefinition item4 = Registry.GetItem("supergrow"); if ((Object)(object)item == (Object)null || (Object)(object)item2 == (Object)null || (Object)(object)item3 == (Object)null) { MelonLogger.Error("Could not find one or more base additive definitions"); return; } if ((Object)(object)item4 == (Object)null) { SuperGrowCreator.CreateSuperGrowItem(); item4 = Registry.GetItem("supergrow"); if ((Object)(object)item4 == (Object)null) { MelonLogger.Warning("Could not find SuperGrow definition; will retry when registry is ready"); return; } } _superGrowRecipe = ScriptableObject.CreateInstance<StationRecipe>(); _superGrowRecipe.IsDiscovered = true; _superGrowRecipe.RecipeTitle = "SuperGrow"; _superGrowRecipe.CookTime_Mins = 5; _superGrowRecipe.Unlocked = true; List<IngredientQuantity> val = new List<IngredientQuantity>(); IngredientQuantity val2 = new IngredientQuantity(); List<ItemDefinition> val3 = new List<ItemDefinition>(); val3.Add(item); val2.Items = val3; val2.Quantity = SuperGrowSettings.PgrRequired.Value; val.Add(val2); IngredientQuantity val4 = new IngredientQuantity(); List<ItemDefinition> val5 = new List<ItemDefinition>(); val5.Add(item2); val4.Items = val5; val4.Quantity = SuperGrowSettings.SpeedGrowRequired.Value; val.Add(val4); IngredientQuantity val6 = new IngredientQuantity(); List<ItemDefinition> val7 = new List<ItemDefinition>(); val7.Add(item3); val6.Items = val7; val6.Quantity = SuperGrowSettings.FertilizerRequired.Value; val.Add(val6); _superGrowRecipe.Ingredients = val; _superGrowRecipe.Product = new ItemQuantity { Item = item4, Quantity = SuperGrowSettings.OutputQuantity.Value }; _superGrowRecipe.FinalLiquidColor = SuperGrowVisuals.PourColor; } private static bool TryGetStationItemTemplate(out StationItem templateStationItem) { templateStationItem = null; string[] array = new string[4] { "acid", "pgr", "speedgrow", "fertilizer" }; string[] array2 = array; for (int i = 0; i < array2.Length; i++) { ItemDefinition item = Registry.GetItem(array2[i]); StorableItemDefinition val = ((item != null) ? ((Il2CppObjectBase)item).TryCast<StorableItemDefinition>() : null); if ((Object)(object)((val != null) ? val.StationItem : null) != (Object)null) { templateStationItem = val.StationItem; return true; } } if (!_loggedMissingStationItemTemplate) { _loggedMissingStationItemTemplate = true; MelonLogger.Warning("Could not find any StationItem template (acid/pgr/speedgrow/fertilizer)"); array2 = array; foreach (string text in array2) { ItemDefinition item2 = Registry.GetItem(text); StorableItemDefinition val2 = ((item2 != null) ? ((Il2CppObjectBase)item2).TryCast<StorableItemDefinition>() : null); MelonLogger.Warning($"{text}: def={(((Object)(object)val2 == (Object)null) ? "<null>" : ((object)val2).GetType().FullName)} stationItem={(((Object)(object)((val2 != null) ? val2.StationItem : null) == (Object)null) ? "<null>" : ((object)val2.StationItem).GetType().FullName)}"); } } return false; } [HarmonyPatch(typeof(Registry), "Start")] [HarmonyPostfix] private static void Registry_Start_Postfix() { if (_loggedRegistryStart) { return; } _loggedRegistryStart = true; try { SuperGrowCreator.CreateSuperGrowItem(); EnsureAdditiveStationItemPrefabs(); } catch (Exception ex) { MelonLogger.Error("Registry.Start hook failed: " + ex.Message); MelonLogger.Error(ex.StackTrace ?? "<no stack trace>"); } } public static void SetupAdditiveStationItems() { if (_additivesPatched) { return; } try { CachePourablePrefab("pgr", "growing/pgr/PGR_Pourable"); CachePourablePrefab("speedgrow", "growing/speedgrow/SpeedGrow_Pourable"); CachePourablePrefab("fertilizer", "growing/fertilizer/Fertilizer_Pourable"); if (EnsureAdditiveStationItemPrefabs()) { _additivesPatched = true; } } catch (Exception ex) { MelonLogger.Error("Failed to set up additive StationItems: " + ex.Message); MelonLogger.Error(ex.StackTrace); } } [HarmonyPatch(typeof(StoredItem), "InitializeStoredItem")] [HarmonyPostfix] private static void StoredItem_InitializeStoredItem_Postfix(StoredItem __instance, StorableItemInstance _item) { try { object obj; if (_item == null) { obj = null; } else { ItemDefinition definition = ((ItemInstance)_item).Definition; obj = ((definition != null) ? definition.ID : null); } if (!((string?)obj != "supergrow")) { ApplySuperGrowMaterialsToRenderers(Il2CppArrayBase<Renderer>.op_Implicit(((Component)__instance).GetComponentsInChildren<Renderer>(true))); } } catch (Exception ex) { MelonLogger.Error("Failed to apply SuperGrow visuals to stored item: " + ex.Message); MelonLogger.Error(ex.StackTrace ?? "<no stack trace>"); } } private static void SetPendingStationTrashReskins(List<PendingTrashReskin> reskins) { _pendingStationTrashReskins.Clear(); if (reskins.Count > 0) { _pendingStationTrashReskins.AddRange(reskins); _pendingStationTrashReskinExpireTick = Environment.TickCount + 5000; } else { _pendingStationTrashReskinExpireTick = 0; } } [HarmonyPatch(typeof(ChemistryStation), "CreateTrash")] [HarmonyPrefix] private static void ChemistryStation_CreateTrash_Prefix(ChemistryStation __instance, List<StationItem> mixerItems) { try { if (mixerItems == null) { return; } List<PendingTrashReskin> list = new List<PendingTrashReskin>(); for (int i = 0; i < mixerItems.Count; i++) { StationItem val = mixerItems[i]; if ((Object)(object)val == (Object)null || (Object)(object)((Component)val).gameObject == (Object)null) { continue; } string text = TryParseAdditiveIdFromStationItemName(((Object)((Component)val).gameObject).name); if (text != null) { string text2 = (((Object)(object)val.TrashPrefab != (Object)null) ? val.TrashPrefab.ID : null); if (!string.IsNullOrEmpty(text2)) { list.Add(new PendingTrashReskin(text2, text)); } } } SetPendingStationTrashReskins(list); } catch { } } private static string? TryParseAdditiveIdFromStationItemName(string? stationItemName) { if (string.IsNullOrEmpty(stationItemName)) { return null; } int num = stationItemName.IndexOf("SuperGrow_StationItemPrefab_", StringComparison.OrdinalIgnoreCase); if (num < 0) { return null; } num += "SuperGrow_StationItemPrefab_".Length; if (num >= stationItemName.Length) { return null; } int num2 = stationItemName.IndexOf('(', num); if (num2 < 0) { num2 = stationItemName.Length; } string text = stationItemName.Substring(num, num2 - num).Trim(); if (text.Length == 0) { return null; } text = text.ToLowerInvariant(); switch (text) { default: return null; case "pgr": case "speedgrow": case "fertilizer": case "supergrow": return text; } } [HarmonyPatch(typeof(TrashItem), "Start")] [HarmonyPostfix] private static void TrashItem_Start_Postfix(TrashItem __instance) { try { if (_pendingStationTrashReskins.Count == 0) { return; } if (_pendingStationTrashReskinExpireTick != 0 && Environment.TickCount - _pendingStationTrashReskinExpireTick >= 0) { _pendingStationTrashReskins.Clear(); _pendingStationTrashReskinExpireTick = 0; return; } string iD = __instance.ID; if (string.IsNullOrEmpty(iD)) { return; } for (int i = 0; i < _pendingStationTrashReskins.Count; i++) { PendingTrashReskin pendingTrashReskin = _pendingStationTrashReskins[i]; if (!(pendingTrashReskin.TrashId != iD)) { _pendingStationTrashReskins.RemoveAt(i); SwapTrashItemVisualsById(pendingTrashReskin.AdditiveId, __instance); break; } } } catch (Exception ex) { MelonLogger.Error("Failed to apply SuperGrow visuals to trash item: " + ex.Message); MelonLogger.Error(ex.StackTrace ?? "<no stack trace>"); } } private static bool IsChemistryBeakerFillable(Fillable fillable) { if ((Object)(object)fillable == (Object)null) { return false; } LiquidContainer liquidContainer = fillable.LiquidContainer; if ((Object)(object)liquidContainer == (Object)null || (Object)(object)((Component)liquidContainer).transform == (Object)null) { return false; } Transform transform = ((Component)liquidContainer).transform; if (!string.Equals(((Object)transform).name, "Liquid", StringComparison.OrdinalIgnoreCase)) { return false; } Transform parent = transform.parent; if ((Object)(object)parent == (Object)null || !string.Equals(((Object)parent).name, "Beaker", StringComparison.OrdinalIgnoreCase)) { return false; } Transform parent2 = parent.parent; if ((Object)(object)parent2 == (Object)null || !((Object)parent2).name.StartsWith("Beaker", StringComparison.OrdinalIgnoreCase)) { return false; } Transform val = parent2; while ((Object)(object)val != (Object)null) { if (((Object)val).name != null && ((Object)val).name.IndexOf("ChemistryStation", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } val = val.parent; } return false; } private static void CachePourablePrefab(string additiveId, string pourablePath) { if (!_pourablePrefabs.ContainsKey(additiveId)) { GameObject val = Resources.Load<GameObject>(pourablePath); if ((Object)(object)val != (Object)null) { _pourablePrefabs[additiveId] = val; } else { MelonLogger.Warning("Could not load pourable prefab for " + additiveId + " at " + pourablePath); } } } private static Transform? FindStationItemBottleContainer(StationItem stationItem) { Transform val = ((Component)stationItem).transform.Find("Pourable"); if ((Object)(object)val == (Object)null) { return null; } Transform result = null; int childCount = val.childCount; for (int i = 0; i < childCount; i++) { Transform child = val.GetChild(i); if ((Object)(object)child != (Object)null && ((Object)child).name.IndexOf("Bottle", StringComparison.OrdinalIgnoreCase) >= 0) { result = child; break; } } return result; } private static void SwapBottleMeshesAndMaterials(GameObject templatePrefab, Transform targetRoot) { Il2CppArrayBase<MeshFilter> componentsInChildren = templatePrefab.GetComponentsInChildren<MeshFilter>(true); foreach (MeshFilter componentsInChild in ((Component)targetRoot).GetComponentsInChildren<MeshFilter>(true)) { if ((Object)(object)componentsInChild == (Object)null) { continue; } string text = ((Object)componentsInChild).name.ToLowerInvariant(); foreach (MeshFilter item in componentsInChildren) { if ((Object)(object)item == (Object)null) { continue; } string text2 = ((Object)item).name.ToLowerInvariant(); if ((text.Contains("body") && text2.Contains("body")) || (text.Contains("label") && text2.Contains("label")) || (text.Contains("lid") && text2.Contains("lid"))) { componentsInChild.sharedMesh = item.sharedMesh; MeshRenderer component = ((Component)componentsInChild).GetComponent<MeshRenderer>(); MeshRenderer component2 = ((Component)item).GetComponent<MeshRenderer>(); if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null) { ((Renderer)component).sharedMaterials = ((Renderer)component2).sharedMaterials; } break; } } } } private static void ApplySuperGrowMaterialsToRenderers(Renderer[]? renderers) { SuperGrowVisuals.ApplySuperGrowMaterialsToRenderers(renderers); } private static void SetupAdditiveStationItem(string additiveId, StationItem templateStationItem) { ItemDefinition item = Registry.GetItem(additiveId); StorableItemDefinition val = ((item != null) ? ((Il2CppObjectBase)item).TryCast<StorableItemDefinition>() : null); if ((Object)(object)val == (Object)null) { MelonLogger.Warning("Could not find additive: " + additiveId); } else if (!((Object)(object)val.StationItem != (Object)null)) { val.StationItem = templateStationItem; } } private static void SwapTrashItemVisualsById(string id, TrashItem trashItem) { if ((Object)(object)trashItem == (Object)null || string.IsNullOrEmpty(id)) { return; } bool flag = id == "supergrow"; if (!flag && id != "pgr" && id != "speedgrow" && id != "fertilizer") { return; } GameObject value = null; if (flag) { _pourablePrefabs.TryGetValue("pgr", out value); } else { _pourablePrefabs.TryGetValue(id, out value); } if ((Object)(object)value == (Object)null) { return; } try { if (!((Object)(object)((Component)trashItem).transform == (Object)null)) { SwapBottleMeshesAndMaterials(value, ((Component)trashItem).transform); if (flag) { ApplySuperGrowMaterialsToRenderers(Il2CppArrayBase<Renderer>.op_Implicit(((Component)trashItem).GetComponentsInChildren<Renderer>(true))); } } } catch (Exception ex) { MelonLogger.Error("Failed to swap trash visuals for " + id + ": " + ex.Message); MelonLogger.Error(ex.StackTrace); } } private static void SwapStationItemVisualsById(string id, StationItem stationItem) { //IL_0115: Unknown result type (might be due to invalid IL or missing references) //IL_011f: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)stationItem == (Object)null || string.IsNullOrEmpty(id)) { return; } bool flag = id == "supergrow"; if (!flag && id != "pgr" && id != "speedgrow" && id != "fertilizer") { return; } GameObject value = null; if (flag) { _pourablePrefabs.TryGetValue("pgr", out value); } else { _pourablePrefabs.TryGetValue(id, out value); } if ((Object)(object)value == (Object)null) { return; } try { Transform val = FindStationItemBottleContainer(stationItem); if ((Object)(object)val == (Object)null) { return; } SwapBottleMeshesAndMaterials(value, val); if (flag) { ApplySuperGrowMaterialsToRenderers(Il2CppArrayBase<Renderer>.op_Implicit(((Component)val).GetComponentsInChildren<Renderer>(true))); } object obj; if (!((Object)(object)((Component)stationItem).transform != (Object)null)) { obj = null; } else { Transform obj2 = ((Component)stationItem).transform.Find("Pourable"); obj = ((obj2 != null) ? ((Component)obj2).GetComponent<PourableModule>() : null); } PourableModule val2 = (PourableModule)obj; if ((Object)(object)val2 != (Object)null && (Object)(object)val2.LiquidContainer != (Object)null) { LiquidContainer liquidContainer = val2.LiquidContainer; if ((Object)(object)liquidContainer.LiquidVolume != (Object)null) { Transform transform = ((Component)liquidContainer.LiquidVolume).transform; transform.localScale *= 0.65f; } liquidContainer.MaxLevel *= 0.65f; if (_additiveColors.TryGetValue(id, out var value2)) { val2.LiquidType = id; val2.LiquidColor = value2; val2.PourParticlesColor = value2; } } } catch (Exception ex) { MelonLogger.Error("Failed to swap station item visuals for " + id + ": " + ex.Message); MelonLogger.Error(ex.StackTrace); } } private static void SwapStationItemVisualsById(string id, StationItem stationItem, StorableItemDefinition itemDef) { if (!((Object)(object)stationItem == (Object)null) && !((Object)(object)itemDef == (Object)null)) { SwapStationItemVisualsById(id, stationItem); } } } [HarmonyPatch] internal static class GrowContainerPatches { private const string SuperGrowBottleTrashId = "supergrow_bottle"; private static bool _loggedGrowContainerTrashPrefabAssignException; private static readonly Vector3 HiddenPrefabPosition = new Vector3(100000f, 100000f, 100000f); private static Pourable? _superGrowPourablePrefab; private static int _removeItemDepth; private static bool _shouldReskinNextTrashSpawn; private static readonly HashSet<string> _loggedReskinnedTrashIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static void InjectSuperGrowIntoAllowedAdditives(GrowContainer container) { try { ItemDefinition item = Registry.GetItem("supergrow"); AdditiveDefinition val = ((item != null) ? ((Il2CppObjectBase)item).TryCast<AdditiveDefinition>() : null); if ((Object)(object)val == (Object)null) { return; } Il2CppReferenceArray<AdditiveDefinition> allowedAdditives = container.AllowedAdditives; int num = ((Il2CppArrayBase<AdditiveDefinition>)(object)allowedAdditives)?.Length ?? 0; for (int i = 0; i < num; i++) { AdditiveDefinition val2 = ((Il2CppArrayBase<AdditiveDefinition>)(object)allowedAdditives)[i]; if ((Object)(object)val2 != (Object)null && ((ItemDefinition)val2).ID == "supergrow") { return; } } AdditiveDefinition[] array = (AdditiveDefinition[])(object)new AdditiveDefinition[num + 1]; for (int j = 0; j < num; j++) { array[j] = ((Il2CppArrayBase<AdditiveDefinition>)(object)allowedAdditives)[j]; } array[num] = val; container.AllowedAdditives = new Il2CppReferenceArray<AdditiveDefinition>(array); } catch (Exception ex) { MelonLogger.Error("Failed to inject SuperGrow into AllowedAdditives: " + ex.Message); } } [HarmonyPatch(typeof(GrowContainer), "InitializeGridItem")] [HarmonyPrefix] private static void GrowContainer_InitializeGridItem_Prefix(GrowContainer __instance) { InjectSuperGrowIntoAllowedAdditives(__instance); } private static Pourable? GetOrCreateSuperGrowPourablePrefab(Pourable basePrefab) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: 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) if ((Object)(object)_superGrowPourablePrefab != (Object)null && (Object)(object)((Component)_superGrowPourablePrefab).gameObject != (Object)null) { return _superGrowPourablePrefab; } if ((Object)(object)basePrefab == (Object)null || (Object)(object)((Component)basePrefab).gameObject == (Object)null) { return null; } try { GameObject val = Object.Instantiate<GameObject>(((Component)basePrefab).gameObject); ((Object)val).name = "SuperGrow_PourablePrefab"; ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)val); val.transform.position = HiddenPrefabPosition; if (!val.activeSelf) { val.SetActive(true); } Pourable component = val.GetComponent<Pourable>(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val); return null; } PourableAdditive component2 = val.GetComponent<PourableAdditive>(); if ((Object)(object)component2 != (Object)null) { component2.LiquidColor = SuperGrowVisuals.PourColor; } foreach (ParticleSystem componentsInChild in val.GetComponentsInChildren<ParticleSystem>(true)) { if (!((Object)(object)componentsInChild == (Object)null)) { componentsInChild.main.startColor = MinMaxGradient.op_Implicit(SuperGrowVisuals.PourColor); } } SuperGrowVisuals.ApplySuperGrowMaterialsToRenderers(Il2CppArrayBase<Renderer>.op_Implicit(val.GetComponentsInChildren<Renderer>(true))); try { TrashManager val2 = Object.FindObjectOfType<TrashManager>(); if ((Object)(object)val2 != (Object)null) { TrashItem trashPrefab = val2.GetTrashPrefab("supergrow_bottle"); if ((Object)(object)trashPrefab != (Object)null) { component.TrashItem = trashPrefab; } } } catch (Exception ex) { if (!_loggedGrowContainerTrashPrefabAssignException) { _loggedGrowContainerTrashPrefabAssignException = true; MelonLogger.Warning("Failed to assign SuperGrow trash prefab to grow-container pourable: " + ex.Message); MelonLogger.Warning(ex.StackTrace ?? "<no stack trace>"); } } _superGrowPourablePrefab = component; return _superGrowPourablePrefab; } catch (Exception ex2) { MelonLogger.Error("Failed to create SuperGrow pourable prefab: " + ex2.Message); MelonLogger.Error(ex2.StackTrace); return null; } } [HarmonyPatch(typeof(Equippable_Additive), "Equip")] [HarmonyPostfix] private static void Equippable_Additive_Equip_Postfix(Equippable_Additive __instance, ItemInstance item) { try { object obj; if (item == null) { obj = null; } else { ItemDefinition definition = item.Definition; obj = ((definition != null) ? definition.ID : null); } if ((string?)obj != "supergrow") { return; } SuperGrowVisuals.ApplySuperGrowMaterialsToRenderers(Il2CppArrayBase<Renderer>.op_Implicit(((Component)__instance).GetComponentsInChildren<Renderer>(true))); Pourable pourablePrefab = ((Equippable_Pourable)__instance).PourablePrefab; if (!((Object)(object)pourablePrefab == (Object)null)) { Pourable orCreateSuperGrowPourablePrefab = GetOrCreateSuperGrowPourablePrefab(pourablePrefab); if ((Object)(object)orCreateSuperGrowPourablePrefab != (Object)null) { ((Equippable_Pourable)__instance).PourablePrefab = orCreateSuperGrowPourablePrefab; } } } catch (Exception ex) { MelonLogger.Error("Failed to apply SuperGrow grow-container pour visuals: " + ex.Message); MelonLogger.Error(ex.StackTrace); } } [HarmonyPatch(typeof(GrowContainerPourTask), "RemoveItem")] [HarmonyPrefix] private static void GrowContainerPourTask_RemoveItem_Prefix() { _removeItemDepth++; } [HarmonyPatch(typeof(GrowContainerPourTask), "RemoveItem")] [HarmonyFinalizer] private static void GrowContainerPourTask_RemoveItem_Finalizer(Exception __exception) { _removeItemDepth = Math.Max(0, _removeItemDepth - 1); _shouldReskinNextTrashSpawn = false; } [HarmonyPatch(typeof(PlayerInventory), "RemoveAmountOfItem")] [HarmonyPrefix] private static void PlayerInventory_RemoveAmountOfItem_Prefix(string ID) { if (_removeItemDepth > 0 && string.Equals(ID, "supergrow", StringComparison.OrdinalIgnoreCase)) { _shouldReskinNextTrashSpawn = true; } } [HarmonyPatch(typeof(TrashManager), "CreateAndReturnTrashItem")] [HarmonyPostfix] private static void TrashManager_CreateAndReturnTrashItem_Postfix_GrowContainerReskin(string id, object __result) { if (!_shouldReskinNextTrashSpawn) { return; } _shouldReskinNextTrashSpawn = false; try { if (__result != null) { object? obj = AccessTools.Property(__result.GetType(), "gameObject")?.GetValue(__result); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if (!((Object)(object)val == (Object)null)) { SuperGrowVisuals.ApplySuperGrowMaterialsToRenderers(Il2CppArrayBase<Renderer>.op_Implicit(val.GetComponentsInChildren<Renderer>(true))); } } } catch (Exception ex) { MelonLogger.Error("Failed to reskin grow-container trash for SuperGrow: " + ex.Message); MelonLogger.Error(ex.StackTrace); } } } } namespace SuperGrow.Features { internal static class SuperGrowCreator { private static AdditiveDefinition? _superGrowDefinition; private static bool _loggedMissingAdditiveTemplate; private static bool _loggedRegistryUnavailable; public static void CreateSuperGrowItem() { try { if (!((Object)(object)Registry.GetItem("supergrow") != (Object)null)) { CreateAdditiveDefinition(); _ = (Object)(object)Registry.GetItem("supergrow") != (Object)null; } } catch (Exception ex) { MelonLogger.Error("Failed to create SuperGrow item: " + ex.Message); MelonLogger.Error(ex.StackTrace); } } private static void CreateAdditiveDefinition() { //IL_0194: Unknown result type (might be due to invalid IL or missing references) //IL_0204: Unknown result type (might be due to invalid IL or missing references) //IL_0254: Unknown result type (might be due to invalid IL or missing references) //IL_02c9: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02e3: Unknown result type (might be due to invalid IL or missing references) //IL_02ef: Expected O, but got Unknown if (!Singleton<Registry>.InstanceExists && !_loggedRegistryUnavailable) { _loggedRegistryUnavailable = true; MelonLogger.Warning("Registry singleton is not available yet; will retry"); } Registry val = Singleton<Registry>.Instance; if ((Object)(object)val == (Object)null) { val = Object.FindObjectOfType<Registry>(); } if ((Object)(object)val == (Object)null) { if (!_loggedRegistryUnavailable) { _loggedRegistryUnavailable = true; MelonLogger.Warning("Registry instance is not available; cannot add SuperGrow definition yet."); } return; } ItemDefinition item = Registry.GetItem("pgr"); object obj = ((item != null) ? ((Il2CppObjectBase)item).TryCast<AdditiveDefinition>() : null); if (obj == null) { ItemDefinition item2 = Registry.GetItem("speedgrow"); obj = ((item2 != null) ? ((Il2CppObjectBase)item2).TryCast<AdditiveDefinition>() : null); if (obj == null) { ItemDefinition item3 = Registry.GetItem("fertilizer"); obj = ((item3 != null) ? ((Il2CppObjectBase)item3).TryCast<AdditiveDefinition>() : null); } } AdditiveDefinition val2 = (AdditiveDefinition)obj; if ((Object)(object)val2 == (Object)null) { if (!_loggedMissingAdditiveTemplate) { _loggedMissingAdditiveTemplate = true; ItemDefinition item4 = Registry.GetItem("pgr"); ItemDefinition item5 = Registry.GetItem("speedgrow"); ItemDefinition item6 = Registry.GetItem("fertilizer"); MelonLogger.Error("Could not find any existing additive to clone from!"); MelonLogger.Error("pgr=" + (((Object)(object)item4 == (Object)null) ? "<null>" : ((object)item4).GetType().FullName)); MelonLogger.Error("speedgrow=" + (((Object)(object)item5 == (Object)null) ? "<null>" : ((object)item5).GetType().FullName)); MelonLogger.Error("fertilizer=" + (((Object)(object)item6 == (Object)null) ? "<null>" : ((object)item6).GetType().FullName)); } return; } if ((Object)(object)_superGrowDefinition != (Object)null) { val.AddToRegistry((ItemDefinition)(object)_superGrowDefinition); return; } _superGrowDefinition = ScriptableObject.CreateInstance<AdditiveDefinition>(); ((ItemDefinition)_superGrowDefinition).Category = ((ItemDefinition)val2).Category; ((ItemDefinition)_superGrowDefinition).StackLimit = ((ItemDefinition)val2).StackLimit; ((ItemDefinition)_superGrowDefinition).Keywords = ((ItemDefinition)val2).Keywords; ((ItemDefinition)_superGrowDefinition).AvailableInDemo = ((ItemDefinition)val2).AvailableInDemo; ((ItemDefinition)_superGrowDefinition).UsableInFilters = ((ItemDefinition)val2).UsableInFilters; ((StorableItemDefinition)_superGrowDefinition).ResellMultiplier = ((StorableItemDefinition)val2).ResellMultiplier; ((StorableItemDefinition)_superGrowDefinition).ShopCategories = ((StorableItemDefinition)val2).ShopCategories; ((ItemDefinition)_superGrowDefinition).legalStatus = ((ItemDefinition)val2).legalStatus; ((ItemDefinition)_superGrowDefinition).Equippable = ((ItemDefinition)val2).Equippable; ((StorableItemDefinition)_superGrowDefinition).StoredItem = ((StorableItemDefinition)val2).StoredItem; ((StorableItemDefinition)_superGrowDefinition).StationItem = ((StorableItemDefinition)val2).StationItem; ((StorableItemDefinition)_superGrowDefinition).BasePurchasePrice = ((StorableItemDefinition)val2).BasePurchasePrice; ((ItemDefinition)_superGrowDefinition).LabelDisplayColor = ((ItemDefinition)val2).LabelDisplayColor; ((ItemDefinition)_superGrowDefinition).ID = "supergrow"; ((ItemDefinition)_superGrowDefinition).Name = "SuperGrow"; ((ItemDefinition)_superGrowDefinition).Description = "A powerful growth enhancer combining the effects of PGR, Speed Grow, and Fertilizer. Apply to plants for increased yield, faster growth, and improved quality."; ((Object)_superGrowDefinition).name = "SuperGrow"; Sprite iconSprite = SuperGrowAssets.GetIconSprite(); ((ItemDefinition)_superGrowDefinition).Icon = iconSprite ?? ((ItemDefinition)val2).Icon; if ((Object)(object)val2.DisplayMaterial != (Object)null) { Material displayMaterial = new Material(val2.DisplayMaterial) { color = new Color(0.3f, 0.9f, 0.3f, 1f) }; _superGrowDefinition.DisplayMaterial = displayMaterial; } _superGrowDefinition.QualityChange = SuperGrowSettings.QualityChange.Value; _superGrowDefinition.YieldMultiplier = SuperGrowSettings.YieldMultiplier.Value; _superGrowDefinition.InstantGrowth = SuperGrowSettings.InstantGrowth.Value; val.AddToRegistry((ItemDefinition)(object)_superGrowDefinition); } } }
SuperGrow_Mono.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using HarmonyLib; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using ScheduleOne; using ScheduleOne.DevUtilities; using ScheduleOne.Equipping; using ScheduleOne.Growing; using ScheduleOne.ItemFramework; using ScheduleOne.ObjectScripts; using ScheduleOne.PlayerScripts; using ScheduleOne.PlayerTasks; using ScheduleOne.PlayerTasks.Tasks; using ScheduleOne.StationFramework; using ScheduleOne.Storage; using ScheduleOne.Trash; using ScheduleOne.UI.Stations; using SuperGrow; using SuperGrow.Features; using SuperGrow.Patches; using SuperGrow.Utils; using TMPro; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: MelonInfo(typeof(Core), "SuperGrow", "1.3.0", "HazDS", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: AssemblyCompany("SuperGrow")] [assembly: AssemblyConfiguration("Release")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+210d764bdf4017213cdf984dcb70d397bf5d2d97")] [assembly: AssemblyProduct("SuperGrow")] [assembly: AssemblyTitle("SuperGrow")] [assembly: NeutralResourcesLanguage("en-US")] [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 SuperGrow { internal static class SuperGrowSettings { private static bool _initialized; private static MelonPreferences_Category? _prefsCategory; public static MelonPreferences_Entry<int> PgrRequired { get; private set; } public static MelonPreferences_Entry<int> SpeedGrowRequired { get; private set; } public static MelonPreferences_Entry<int> FertilizerRequired { get; private set; } public static MelonPreferences_Entry<int> OutputQuantity { get; private set; } public static MelonPreferences_Entry<float> YieldMultiplier { get; private set; } public static MelonPreferences_Entry<float> InstantGrowth { get; private set; } public static MelonPreferences_Entry<float> QualityChange { get; private set; } public static void Initialize() { if (!_initialized) { _prefsCategory = MelonPreferences.CreateCategory("SuperGrow", "SuperGrow Settings"); PgrRequired = _prefsCategory.CreateEntry<int>("PgrRequired", 1, "PGR Required", "Amount of PGR needed per craft", false, false, (ValueValidator)null, (string)null); SpeedGrowRequired = _prefsCategory.CreateEntry<int>("SpeedGrowRequired", 1, "Speed Grow Required", "Amount of Speed Grow needed per craft", false, false, (ValueValidator)null, (string)null); FertilizerRequired = _prefsCategory.CreateEntry<int>("FertilizerRequired", 1, "Fertilizer Required", "Amount of Fertilizer needed per craft", false, false, (ValueValidator)null, (string)null); OutputQuantity = _prefsCategory.CreateEntry<int>("OutputQuantity", 3, "Output Quantity", "Amount of SuperGrow produced per craft", false, false, (ValueValidator)null, (string)null); YieldMultiplier = _prefsCategory.CreateEntry<float>("YieldMultiplier", 1.5f, "Yield Multiplier", "Yield multiplier applied to plants (1.5 = 50% more yield)", false, false, (ValueValidator)null, (string)null); InstantGrowth = _prefsCategory.CreateEntry<float>("InstantGrowth", 0.5f, "Instant Growth", "Instant growth progress (0.5 = 50% instant growth)", false, false, (ValueValidator)null, (string)null); QualityChange = _prefsCategory.CreateEntry<float>("QualityChange", 1f, "Quality Change", "Quality modifier applied to plants", false, false, (ValueValidator)null, (string)null); Clamp(PgrRequired, 1, 10); Clamp(SpeedGrowRequired, 1, 10); Clamp(FertilizerRequired, 1, 10); Clamp(OutputQuantity, 1, 10); Clamp(YieldMultiplier, 0.1f, 10f); Clamp(InstantGrowth, 0f, 1f); Clamp(QualityChange, -1f, 1f); _initialized = true; } } private static void Clamp(MelonPreferences_Entry<int> entry, int min, int max) { if (entry.Value < min) { entry.Value = min; } if (entry.Value > max) { entry.Value = max; } } private static void Clamp(MelonPreferences_Entry<float> entry, float min, float max) { if (entry.Value < min) { entry.Value = min; } if (entry.Value > max) { entry.Value = max; } } } public class Core : MelonMod { private bool _itemsInitialized; private int _nextInitAttemptTick; private const int InitAttemptIntervalMs = 250; public static Core Instance { get; private set; } public override void OnInitializeMelon() { Instance = this; SuperGrowSettings.Initialize(); MelonLogger.Msg("[SuperGrow v1.3.0] Initialized."); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { if (sceneName == "Menu") { _itemsInitialized = false; _nextInitAttemptTick = 0; ChemistryStationPatches.Reset(); } } public override void OnUpdate() { if (_itemsInitialized && (Object)(object)Registry.GetItem("supergrow") != (Object)null) { return; } if ((Object)(object)Registry.GetItem("supergrow") != (Object)null) { _itemsInitialized = true; } else if (ShouldAttemptInitNow()) { _itemsInitialized = false; if (SuperGrowWorldState.IsRegistryReady()) { SuperGrowCreator.CreateSuperGrowItem(); _itemsInitialized = (Object)(object)Registry.GetItem("supergrow") != (Object)null; } } } private bool ShouldAttemptInitNow() { int tickCount = Environment.TickCount; if (tickCount - _nextInitAttemptTick < 0) { return false; } _nextInitAttemptTick = tickCount + 250; return true; } } internal static class SuperGrowAssets { private const string IconResourceName = "SuperGrow.Assets.SuperGrow_Icon.png"; private const string LabelResourceName = "SuperGrow.Assets.SuperGrow_Label.png"; private static Sprite? _icon; private static Texture2D? _labelTexture; private static bool _loggedIconLoadException; private static bool _loggedLabelLoadException; private static bool _loggedImageLoadException; public static Sprite? GetIconSprite() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0033: Expected O, but got Unknown //IL_0071: Unknown result type (might be due to invalid IL or missing references) //IL_0080: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_icon != (Object)null) { return _icon; } try { byte[] array = LoadEmbeddedResourceBytes("SuperGrow.Assets.SuperGrow_Icon.png"); if (array == null) { return null; } Texture2D val = new Texture2D(2, 2, (TextureFormat)4, false); if (!TryLoadImage(val, array)) { MelonLogger.Warning("Failed to decode SuperGrow.Assets.SuperGrow_Icon.png"); return null; } ((Object)val).name = "SuperGrow_Icon"; _icon = Sprite.Create(val, new Rect(0f, 0f, (float)((Texture)val).width, (float)((Texture)val).height), new Vector2(0.5f, 0.5f), 100f); return _icon; } catch (Exception ex) { if (!_loggedIconLoadException) { _loggedIconLoadException = true; MelonLogger.Warning("Failed to load icon: " + ex.Message); MelonLogger.Warning(ex.StackTrace ?? "<no stack trace>"); } return null; } } public static Texture2D? GetLabelTexture() { //IL_002d: Unknown result type (might be due to invalid IL or missing references) //IL_0037: Expected O, but got Unknown if ((Object)(object)_labelTexture != (Object)null) { return _labelTexture; } try { byte[] array = LoadEmbeddedResourceBytes("SuperGrow.Assets.SuperGrow_Label.png"); if (array == null) { return null; } _labelTexture = new Texture2D(2, 2, (TextureFormat)4, false); if (!TryLoadImage(_labelTexture, array)) { MelonLogger.Warning("Failed to decode SuperGrow.Assets.SuperGrow_Label.png"); _labelTexture = null; return null; } ((Object)_labelTexture).name = "SuperGrow_Label"; return _labelTexture; } catch (Exception ex) { if (!_loggedLabelLoadException) { _loggedLabelLoadException = true; MelonLogger.Error("Failed to load SuperGrow label texture: " + ex.Message); MelonLogger.Error(ex.StackTrace ?? "<no stack trace>"); } _labelTexture = null; return null; } } private static byte[]? LoadEmbeddedResourceBytes(string resourceName) { using Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName); if (stream == null) { MelonLogger.Warning("Could not find embedded resource: " + resourceName); return null; } using MemoryStream memoryStream = new MemoryStream(); stream.CopyTo(memoryStream); return memoryStream.ToArray(); } private static bool TryLoadImage(Texture2D texture, byte[] bytes) { try { Type type = Type.GetType("UnityEngine.ImageConversion, UnityEngine.ImageConversionModule") ?? typeof(Texture2D).Assembly.GetType("UnityEngine.ImageConversion"); if (type == null) { return false; } MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public); bool flag = default(bool); foreach (MethodInfo methodInfo in methods) { if (methodInfo.Name != "LoadImage") { continue; } ParameterInfo[] parameters = methodInfo.GetParameters(); if ((parameters.Length == 2 || parameters.Length == 3) && !(parameters[0].ParameterType != typeof(Texture2D)) && parameters[1].ParameterType == typeof(byte[])) { object obj = ((parameters.Length != 3) ? methodInfo.Invoke(null, new object[2] { texture, bytes }) : methodInfo.Invoke(null, new object[3] { texture, bytes, false })); int num; if (obj is bool) { flag = (bool)obj; num = 1; } else { num = 0; } return (byte)((uint)num & (flag ? 1u : 0u)) != 0; } } return false; } catch (Exception ex) { if (!_loggedImageLoadException) { _loggedImageLoadException = true; MelonLogger.Warning("Failed to decode embedded image bytes via ImageConversion.LoadImage: " + ex.Message); MelonLogger.Warning(ex.StackTrace ?? "<no stack trace>"); } return false; } } } internal static class SuperGrowWorldState { private static bool _loggedReady; private static bool _ready; private static bool _loggedRegistryReadyException; public static bool IsRegistryReady() { try { if (_ready) { return true; } ItemDefinition item = Registry.GetItem("pgr"); ItemDefinition obj = ((item is AdditiveDefinition) ? item : null); ItemDefinition item2 = Registry.GetItem("speedgrow"); AdditiveDefinition val = (AdditiveDefinition)(object)((item2 is AdditiveDefinition) ? item2 : null); ItemDefinition item3 = Registry.GetItem("fertilizer"); AdditiveDefinition val2 = (AdditiveDefinition)(object)((item3 is AdditiveDefinition) ? item3 : null); if ((Object)(object)obj == (Object)null && (Object)(object)val == (Object)null && (Object)(object)val2 == (Object)null) { return false; } _ready = true; if (!_loggedReady) { _loggedReady = true; } return true; } catch (Exception ex) { if (!_loggedRegistryReadyException) { _loggedRegistryReadyException = true; MelonLogger.Warning("Registry readiness check failed: " + ex.Message); MelonLogger.Warning(ex.StackTrace ?? "<no stack trace>"); } return false; } } } } namespace SuperGrow.Utils { public static class Constants { public static class Game { public const string GAME_STUDIO = "TVGS"; public const string GAME_NAME = "Schedule I"; } public static class Additives { public const string PGR = "pgr"; public const string SPEED_GROW = "speedgrow"; public const string FERTILIZER = "fertilizer"; } public static class ItemIds { public const string SUPER_GROW = "supergrow"; } public static class DefaultEffects { public const float YIELD_MULTIPLIER = 1.5f; public const float INSTANT_GROWTH = 0.5f; public const float QUALITY_CHANGE = 1f; } public const string MOD_NAME = "SuperGrow"; public const string MOD_VERSION = "1.3.0"; public const string MOD_AUTHOR = "HazDS"; public const string PREFERENCES_CATEGORY = "SuperGrow"; } internal static class SuperGrowVisuals { internal static readonly Color PourColor = new Color(0.4f, 0.2f, 0.6f, 1f); internal static readonly Color LidTint = new Color(0.6f, 0.4f, 0.8f, 1f); internal static void ApplySuperGrowMaterialsToRenderers(Renderer[]? renderers) { //IL_019a: Unknown result type (might be due to invalid IL or missing references) //IL_01b9: Unknown result type (might be due to invalid IL or missing references) //IL_01d8: Unknown result type (might be due to invalid IL or missing references) if (renderers == null) { return; } Texture2D labelTexture = SuperGrowAssets.GetLabelTexture(); if ((Object)(object)labelTexture == (Object)null) { MelonLogger.Warning("SuperGrow label texture is null, cannot apply"); return; } try { foreach (Renderer val in renderers) { if ((Object)(object)val == (Object)null) { continue; } string text = ((Object)val).name.ToLowerInvariant(); bool flag = text.Contains("label"); if (!flag) { Material[] sharedMaterials = val.sharedMaterials; foreach (Material val2 in sharedMaterials) { if ((Object)(object)val2 != (Object)null && ((Object)val2).name.ToLowerInvariant().Contains("label")) { flag = true; break; } } } bool flag2 = text.Contains("lid"); if (!flag2) { Material[] sharedMaterials = val.sharedMaterials; foreach (Material val3 in sharedMaterials) { if ((Object)(object)val3 != (Object)null && ((Object)val3).name.ToLowerInvariant().Contains("lid")) { flag2 = true; break; } } } if (flag) { Material[] materials = val.materials; foreach (Material val4 in materials) { if (!((Object)(object)val4 == (Object)null)) { val4.mainTexture = (Texture)(object)labelTexture; if (val4.HasProperty("_BaseMap")) { val4.SetTexture("_BaseMap", (Texture)(object)labelTexture); } if (val4.HasProperty("_MainTex")) { val4.SetTexture("_MainTex", (Texture)(object)labelTexture); } } } val.materials = materials; } else { if (!flag2) { continue; } Material[] materials2 = val.materials; foreach (Material val5 in materials2) { if (!((Object)(object)val5 == (Object)null)) { val5.color = LidTint; if (val5.HasProperty("_BaseColor")) { val5.SetColor("_BaseColor", LidTint); } if (val5.HasProperty("_Color")) { val5.SetColor("_Color", LidTint); } } } val.materials = materials2; } } } catch (Exception ex) { MelonLogger.Error("Failed to apply SuperGrow materials: " + ex.Message); MelonLogger.Error(ex.StackTrace); } } } } namespace SuperGrow.Patches { [HarmonyPatch] internal static class ChemistryStationPatches { private readonly struct PendingTrashReskin { public string TrashId { get; } public string AdditiveId { get; } public PendingTrashReskin(string trashId, string additiveId) { TrashId = trashId; AdditiveId = additiveId; } } [CompilerGenerated] private sealed class <DelayedChemistryIngredientAudit>d__23 : IEnumerator<object>, IEnumerator, IDisposable { private int <>1__state; private object <>2__current; object IEnumerator<object>.Current { [DebuggerHidden] get { return <>2__current; } } object IEnumerator.Current { [DebuggerHidden] get { return <>2__current; } } [DebuggerHidden] public <DelayedChemistryIngredientAudit>d__23(int <>1__state) { this.<>1__state = <>1__state; } [DebuggerHidden] void IDisposable.Dispose() { <>1__state = -2; } private bool MoveNext() { //IL_002c: Unknown result type (might be due to invalid IL or missing references) //IL_0036: Expected O, but got Unknown //IL_004c: Unknown result type (might be due to invalid IL or missing references) //IL_0056: Expected O, but got Unknown //IL_006c: Unknown result type (might be due to invalid IL or missing references) //IL_0076: Expected O, but got Unknown switch (<>1__state) { default: return false; case 0: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.1f); <>1__state = 1; return true; case 1: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.4f); <>1__state = 2; return true; case 2: <>1__state = -1; <>2__current = (object)new WaitForSeconds(0.5f); <>1__state = 3; return true; case 3: <>1__state = -1; 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 StationRecipe? _superGrowRecipe; private static bool _additivesPatched; private static bool _loggedMissingStationItemTemplate; private static bool _loggedRegistryStart; private static bool _loggedRecipeNotReady; private static int _superGrowBeginAuditUntilTick; private static int _superGrowBeginAuditSeq; private static ChemistryStation? _superGrowBeginStation; private static int _superGrowBeginStationSeq; private static string? _lastSelectedRecipeProductId; private static string? _lastSelectedRecipeTitle; private static string? _lastSelectedRecipeId; private static int _lastSelectedAtTick; private const string PgrBottleTrashId = "supergrow_pgr_bottle"; private const string SpeedGrowBottleTrashId = "supergrow_speedgrow_bottle"; private const string FertilizerBottleTrashId = "supergrow_fertilizer_bottle"; private const string SuperGrowBottleTrashId = "supergrow_bottle"; private static bool _monoTrashPrefabsInjected; private static readonly Dictionary<string, TrashItem> _monoBottleTrashPrefabByAdditiveId = new Dictionary<string, TrashItem>(); private static bool _loggedMonoTrashPrefabInjectionException; private static int _pendingStationTrashReskinExpireTick; private static readonly List<PendingTrashReskin> _pendingStationTrashReskins = new List<PendingTrashReskin>(); private static readonly Dictionary<string, GameObject> _pourablePrefabs = new Dictionary<string, GameObject>(); private static readonly Dictionary<string, Color> _additiveColors = new Dictionary<string, Color> { { "pgr", new Color(1f, 0.506f, 0.506f, 1f) }, { "speedgrow", new Color(0.506f, 0.812f, 1f, 1f) }, { "fertilizer", new Color(0.639f, 1f, 0.506f, 1f) }, { "supergrow", SuperGrowVisuals.PourColor } }; private const float LiquidScale = 0.65f; public static void Reset() { _superGrowRecipe = null; _additivesPatched = false; _loggedMissingStationItemTemplate = false; _loggedRegistryStart = false; _loggedRecipeNotReady = false; } [HarmonyPatch(typeof(ChemistryStationCanvas), "Awake")] [HarmonyPrefix] private static void ChemistryStationCanvas_Awake_Prefix(ChemistryStationCanvas __instance) { try { if ((Object)(object)__instance == (Object)null) { return; } SuperGrowCreator.CreateSuperGrowItem(); if ((Object)(object)_superGrowRecipe == (Object)null) { CreateSuperGrowRecipe(); } if ((Object)(object)_superGrowRecipe == (Object)null) { if (!_loggedRecipeNotReady) { _loggedRecipeNotReady = true; MelonLogger.Warning("SuperGrow recipe is null; cannot add to chemistry station yet"); } return; } List<StationRecipe> recipes = __instance.Recipes; if (recipes == null) { if (!_loggedRecipeNotReady) { _loggedRecipeNotReady = true; MelonLogger.Warning("ChemistryStationCanvas.Recipes is null; cannot add SuperGrow recipe"); } } else if (!recipes.Contains(_superGrowRecipe)) { recipes.Add(_superGrowRecipe); } } catch (Exception ex) { MelonLogger.Error("Failed to add SuperGrow recipe: " + ex.Message); MelonLogger.Error(ex.StackTrace ?? "<no stack trace>"); } } [HarmonyPatch(typeof(ChemistryStationCanvas), "Awake")] [HarmonyPostfix] private static void ChemistryStationCanvas_Awake_Postfix(ChemistryStationCanvas __instance) { } [HarmonyPatch(typeof(ChemistryStationCanvas), "Start")] [HarmonyPrefix] private static void ChemistryStationCanvas_Start_Prefix(ChemistryStationCanvas __instance) { try { if (!((Object)(object)__instance == (Object)null)) { SetupAdditiveStationItems(); } } catch (Exception ex) { MelonLogger.Error("Failed to add SuperGrow recipe: " + ex.Message); MelonLogger.Error(ex.StackTrace ?? "<no stack trace>"); } } [HarmonyPatch(typeof(ChemistryStationCanvas), "Start")] [HarmonyPostfix] private static void ChemistryStationCanvas_Start_Postfix(ChemistryStationCanvas __instance) { } [HarmonyPatch(typeof(ChemistryStationCanvas), "Open")] [HarmonyPrefix] private static void ChemistryStationCanvas_Open_PrefixAudit(ChemistryStationCanvas __instance, ChemistryStation station) { } [HarmonyPatch(typeof(ChemistryStationCanvas), "SetSelectedRecipe")] [HarmonyPrefix] private static void ChemistryStationCanvas_SetSelectedRecipe_Prefix(ChemistryStationCanvas __instance, StationRecipeEntry entry) { try { StationRecipe val = ((entry != null) ? entry.Recipe : null); string text = SafeGetProductId(val); if (!(text == "<null>") && !(text == "<error>")) { _lastSelectedRecipeProductId = text; _lastSelectedRecipeTitle = SafeGetRecipeEntryTitle(entry); _lastSelectedRecipeId = (((Object)(object)val == (Object)null) ? "<null>" : SafeGetStationRecipeId(val)); _lastSelectedAtTick = Environment.TickCount; } } catch { } } [HarmonyPatch(typeof(ChemistryStationCanvas), "BeginButtonPressed")] [HarmonyPrefix] private static void ChemistryStationCanvas_BeginButtonPressed_Prefix(ChemistryStationCanvas __instance) { try { if (!((Object)(object)__instance == (Object)null)) { StationRecipeEntry? obj = TryGetSelectedRecipeEntry(__instance); string text = SafeGetProductId((obj != null) ? obj.Recipe : null); if (text == "<null>" || text == "<error>") { text = _lastSelectedRecipeProductId ?? text; } if (!(text != "supergrow")) { _superGrowBeginAuditSeq++; _superGrowBeginAuditUntilTick = Environment.TickCount + 10000; _superGrowBeginStation = __instance.ChemistryStation; _superGrowBeginStationSeq = _superGrowBeginAuditSeq; _ = _superGrowBeginAuditSeq; } } } catch (Exception ex) { MelonLogger.Error("SuperGrow Begin audit failed (Prefix): " + ex.Message); MelonLogger.Error(ex.StackTrace ?? "<no stack trace>"); } } [HarmonyPatch(typeof(ChemistryStationCanvas), "BeginButtonPressed")] [HarmonyPostfix] private static void ChemistryStationCanvas_BeginButtonPressed_Postfix(ChemistryStationCanvas __instance) { try { if (!((Object)(object)__instance == (Object)null) && !TickExpired(_superGrowBeginAuditUntilTick)) { int superGrowBeginAuditSeq = _superGrowBeginAuditSeq; ChemistryStation val = __instance.ChemistryStation; if ((Object)(object)val == (Object)null && _superGrowBeginStationSeq == superGrowBeginAuditSeq) { val = _superGrowBeginStation; } _ = (Object)(object)val != (Object)null; } } catch (Exception ex) { MelonLogger.Error("SuperGrow Begin audit failed (Postfix): " + ex.Message); MelonLogger.Error(ex.StackTrace ?? "<no stack trace>"); } } private static bool TickExpired(int untilTick) { return Environment.TickCount - untilTick >= 0; } [IteratorStateMachine(typeof(<DelayedChemistryIngredientAudit>d__23))] private static IEnumerator DelayedChemistryIngredientAudit(int seq, ChemistryStation station) { //yield-return decompiler failed: Unexpected instruction in Iterator.Dispose() return new <DelayedChemistryIngredientAudit>d__23(0); } private static StationRecipeEntry? TryGetSelectedRecipeEntry(ChemistryStationCanvas canvas) { try { Type typeFromHandle = typeof(ChemistryStationCanvas); FieldInfo fieldInfo = AccessTools.Field(typeFromHandle, "selectedRecipe"); if (fieldInfo != null) { object? value = fieldInfo.GetValue(canvas); return (StationRecipeEntry?)((value is StationRecipeEntry) ? value : null); } FieldInfo[] fields = typeFromHandle.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); foreach (FieldInfo fieldInfo2 in fields) { if (!(fieldInfo2.FieldType != typeof(StationRecipeEntry)) && !(fieldInfo2.Name == "RecipeEntryPrefab") && !(fieldInfo2.Name == "InProgressRecipeEntry")) { object? value2 = fieldInfo2.GetValue(canvas); StationRecipeEntry val = (StationRecipeEntry)((value2 is StationRecipeEntry) ? value2 : null); if ((Object)(object)((val != null) ? val.Recipe : null) != (Object)null) { return val; } } } } catch { } return null; } private static string SafeGetRecipeEntryTitle(StationRecipeEntry? entry) { try { return ((Object)(object)entry?.TitleLabel == (Object)null) ? "<null>" : (((TMP_Text)entry.TitleLabel).text ?? "<null>"); } catch { return "<error>"; } } private static bool SafeGetBeginInteractable(ChemistryStationCanvas canvas) { try { return (Object)(object)canvas.BeginButton != (Object)null && ((Selectable)canvas.BeginButton).interactable; } catch { return false; } } private static string SafeGetProductId(StationRecipe? recipe) { try { return recipe?.Product?.Item?.ID ?? "<null>"; } catch { return "<error>"; } } private static string SafeGetStationRecipeId(StationRecipe recipe) { try { return recipe.RecipeID ?? "<null>"; } catch { return "<error>"; } } private static void CreateSuperGrowRecipe() { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown //IL_00f9: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Expected O, but got Unknown //IL_0132: Unknown result type (might be due to invalid IL or missing references) //IL_0139: Expected O, but got Unknown //IL_017c: Unknown result type (might be due to invalid IL or missing references) //IL_0181: Unknown result type (might be due to invalid IL or missing references) //IL_0188: Unknown result type (might be due to invalid IL or missing references) //IL_019d: Expected O, but got Unknown //IL_01a2: Unknown result type (might be due to invalid IL or missing references) //IL_01a7: Unknown result type (might be due to invalid IL or missing references) ItemDefinition item = Registry.GetItem("pgr"); ItemDefinition item2 = Registry.GetItem("speedgrow"); ItemDefinition item3 = Registry.GetItem("fertilizer"); ItemDefinition item4 = Registry.GetItem("supergrow"); if ((Object)(object)item == (Object)null || (Object)(object)item2 == (Object)null || (Object)(object)item3 == (Object)null) { MelonLogger.Error("Could not find one or more base additive definitions"); return; } if ((Object)(object)item4 == (Object)null) { SuperGrowCreator.CreateSuperGrowItem(); item4 = Registry.GetItem("supergrow"); if ((Object)(object)item4 == (Object)null) { MelonLogger.Warning("Could not find SuperGrow definition; will retry when registry is ready"); return; } } _superGrowRecipe = ScriptableObject.CreateInstance<StationRecipe>(); _superGrowRecipe.IsDiscovered = true; _superGrowRecipe.RecipeTitle = "SuperGrow"; _superGrowRecipe.CookTime_Mins = 5; _superGrowRecipe.Unlocked = true; List<IngredientQuantity> list = new List<IngredientQuantity>(); IngredientQuantity val = new IngredientQuantity(); List<ItemDefinition> list2 = new List<ItemDefinition>(); list2.Add(item); val.Items = list2; val.Quantity = SuperGrowSettings.PgrRequired.Value; list.Add(val); IngredientQuantity val2 = new IngredientQuantity(); List<ItemDefinition> list3 = new List<ItemDefinition>(); list3.Add(item2); val2.Items = list3; val2.Quantity = SuperGrowSettings.SpeedGrowRequired.Value; list.Add(val2); IngredientQuantity val3 = new IngredientQuantity(); List<ItemDefinition> list4 = new List<ItemDefinition>(); list4.Add(item3); val3.Items = list4; val3.Quantity = SuperGrowSettings.FertilizerRequired.Value; list.Add(val3); _superGrowRecipe.Ingredients = list; _superGrowRecipe.Product = new ItemQuantity { Item = item4, Quantity = SuperGrowSettings.OutputQuantity.Value }; _superGrowRecipe.FinalLiquidColor = SuperGrowVisuals.PourColor; } private static bool TryGetStationItemTemplate(out StationItem templateStationItem) { templateStationItem = null; string[] array = new string[4] { "acid", "pgr", "speedgrow", "fertilizer" }; string[] array2 = array; for (int i = 0; i < array2.Length; i++) { ItemDefinition item = Registry.GetItem(array2[i]); StorableItemDefinition val = (StorableItemDefinition)(object)((item is StorableItemDefinition) ? item : null); if ((Object)(object)val?.StationItem != (Object)null) { templateStationItem = val.StationItem; return true; } } if (!_loggedMissingStationItemTemplate) { _loggedMissingStationItemTemplate = true; MelonLogger.Warning("Could not find any StationItem template (acid/pgr/speedgrow/fertilizer)"); array2 = array; foreach (string text in array2) { ItemDefinition item2 = Registry.GetItem(text); StorableItemDefinition val2 = (StorableItemDefinition)(object)((item2 is StorableItemDefinition) ? item2 : null); MelonLogger.Warning(text + ": def=" + (((Object)(object)val2 == (Object)null) ? "<null>" : ((object)val2).GetType().FullName) + " stationItem=" + (((Object)(object)val2?.StationItem == (Object)null) ? "<null>" : ((object)val2.StationItem).GetType().FullName)); } } return false; } [HarmonyPatch(typeof(Registry), "Start")] [HarmonyPostfix] private static void Registry_Start_Postfix() { if (_loggedRegistryStart) { return; } _loggedRegistryStart = true; try { SuperGrowCreator.CreateSuperGrowItem(); } catch (Exception ex) { MelonLogger.Error("Registry.Start hook failed: " + ex.Message); MelonLogger.Error(ex.StackTrace ?? "<no stack trace>"); } } public static void SetupAdditiveStationItems() { if (_additivesPatched) { return; } try { CachePourablePrefab("pgr", "growing/pgr/PGR_Pourable"); CachePourablePrefab("speedgrow", "growing/speedgrow/SpeedGrow_Pourable"); CachePourablePrefab("fertilizer", "growing/fertilizer/Fertilizer_Pourable"); if (TryGetStationItemTemplate(out StationItem templateStationItem)) { SetupAdditiveStationItem("pgr", templateStationItem); SetupAdditiveStationItem("speedgrow", templateStationItem); SetupAdditiveStationItem("fertilizer", templateStationItem); _additivesPatched = true; } } catch (Exception ex) { MelonLogger.Error("Failed to set up additive StationItems: " + ex.Message); MelonLogger.Error(ex.StackTrace); } } [HarmonyPatch(typeof(StoredItem), "InitializeStoredItem")] [HarmonyPostfix] private static void StoredItem_InitializeStoredItem_Postfix(StoredItem __instance, StorableItemInstance _item) { try { if (!(((_item == null) ? null : ((ItemInstance)_item).Definition?.ID) != "supergrow")) { ApplySuperGrowMaterialsToRenderers(((Component)__instance).GetComponentsInChildren<Renderer>(true)); } } catch (Exception ex) { MelonLogger.Error("Failed to apply SuperGrow visuals to stored item: " + ex.Message); MelonLogger.Error(ex.StackTrace ?? "<no stack trace>"); } } private static bool TrashPrefabsContainsId(TrashItem[]? prefabs, string id) { if (prefabs == null) { return false; } foreach (TrashItem val in prefabs) { if ((Object)(object)val != (Object)null && val.ID == id) { return true; } } return false; } private static bool TryGetMonoBottleTrashPrefab(string additiveId, out TrashItem prefab) { prefab = null; if (_monoBottleTrashPrefabByAdditiveId.TryGetValue(additiveId, out TrashItem value) && (Object)(object)value != (Object)null) { prefab = value; return true; } TrashManager val = Object.FindObjectOfType<TrashManager>(); if ((Object)(object)val == (Object)null) { return false; } EnsureMonoBottleTrashPrefabsInjected(val); if (_monoBottleTrashPrefabByAdditiveId.TryGetValue(additiveId, out value) && (Object)(object)value != (Object)null) { prefab = value; return true; } return false; } private static void EnsureMonoBottleTrashPrefabsInjected(TrashManager manager) { if (_monoTrashPrefabsInjected || (Object)(object)manager == (Object)null) { return; } try { CachePourablePrefab("pgr", "growing/pgr/PGR_Pourable"); CachePourablePrefab("speedgrow", "growing/speedgrow/SpeedGrow_Pourable"); CachePourablePrefab("fertilizer", "growing/fertilizer/Fertilizer_Pourable"); TrashItem baseTrash = manager.GetTrashPrefab("acid"); TrashItem pgrTrash = manager.GetTrashPrefab("pgr"); if ((Object)(object)baseTrash == (Object)null || (Object)(object)((Component)baseTrash).gameObject == (Object)null) { return; } TrashItem[] prefabs = manager.TrashPrefabs ?? Array.Empty<TrashItem>(); List<TrashItem> additions = new List<TrashItem>(); Ensure("pgr", "supergrow_pgr_bottle"); Ensure("speedgrow", "supergrow_speedgrow_bottle"); Ensure("fertilizer", "supergrow_fertilizer_bottle"); Ensure("supergrow", "supergrow_bottle"); if (additions.Count > 0) { TrashItem[] array = (TrashItem[])(object)new TrashItem[prefabs.Length + additions.Count]; Array.Copy(prefabs, array, prefabs.Length); for (int i = 0; i < additions.Count; i++) { array[prefabs.Length + i] = additions[i]; } manager.TrashPrefabs = array; } _monoTrashPrefabsInjected = true; void Ensure(string additiveId, string newId) { if (!TrashPrefabsContainsId(prefabs, newId)) { GameObject val = ((string.Equals(additiveId, "supergrow", StringComparison.OrdinalIgnoreCase) && (Object)(object)pgrTrash != (Object)null && (Object)(object)((Component)pgrTrash).gameObject != (Object)null) ? ((Component)pgrTrash).gameObject : ((Component)baseTrash).gameObject); GameObject val2 = Object.Instantiate<GameObject>(val); ((Object)val2).name = "SuperGrow_" + additiveId + "_TrashPrefab"; val2.SetActive(val.activeSelf); Object.DontDestroyOnLoad((Object)(object)val2); TrashItem component = val2.GetComponent<TrashItem>(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val2); } else { component.ID = newId; SwapTrashItemVisualsById(additiveId, component); _monoBottleTrashPrefabByAdditiveId[additiveId] = component; additions.Add(component); } } } } catch (Exception ex) { if (!_loggedMonoTrashPrefabInjectionException) { _loggedMonoTrashPrefabInjectionException = true; MelonLogger.Warning("Failed to inject SuperGrow trash prefabs (Mono): " + ex.Message); MelonLogger.Warning(ex.StackTrace ?? "<no stack trace>"); } } } [HarmonyPatch(typeof(TrashManager), "Start")] [HarmonyPostfix] private static void TrashManager_Start_Postfix_Mono(TrashManager __instance) { EnsureMonoBottleTrashPrefabsInjected(__instance); } private static void SetPendingStationTrashReskins(List<PendingTrashReskin> reskins) { _pendingStationTrashReskins.Clear(); if (reskins.Count > 0) { _pendingStationTrashReskins.AddRange(reskins); _pendingStationTrashReskinExpireTick = Environment.TickCount + 5000; } else { _pendingStationTrashReskinExpireTick = 0; } } [HarmonyPatch(typeof(TrashItem), "Start")] [HarmonyPostfix] private static void TrashItem_Start_Postfix(TrashItem __instance) { try { if (_pendingStationTrashReskins.Count == 0) { return; } if (_pendingStationTrashReskinExpireTick != 0 && Environment.TickCount - _pendingStationTrashReskinExpireTick >= 0) { _pendingStationTrashReskins.Clear(); _pendingStationTrashReskinExpireTick = 0; return; } string iD = __instance.ID; if (string.IsNullOrEmpty(iD)) { return; } for (int i = 0; i < _pendingStationTrashReskins.Count; i++) { PendingTrashReskin pendingTrashReskin = _pendingStationTrashReskins[i]; if (!(pendingTrashReskin.TrashId != iD)) { _pendingStationTrashReskins.RemoveAt(i); SwapTrashItemVisualsById(pendingTrashReskin.AdditiveId, __instance); break; } } } catch (Exception ex) { MelonLogger.Error("Failed to apply SuperGrow visuals to trash item: " + ex.Message); MelonLogger.Error(ex.StackTrace ?? "<no stack trace>"); } } private static bool IsChemistryBeakerFillable(Fillable fillable) { if ((Object)(object)fillable == (Object)null) { return false; } LiquidContainer liquidContainer = fillable.LiquidContainer; if ((Object)(object)liquidContainer == (Object)null || (Object)(object)((Component)liquidContainer).transform == (Object)null) { return false; } Transform transform = ((Component)liquidContainer).transform; if (!string.Equals(((Object)transform).name, "Liquid", StringComparison.OrdinalIgnoreCase)) { return false; } Transform parent = transform.parent; if ((Object)(object)parent == (Object)null || !string.Equals(((Object)parent).name, "Beaker", StringComparison.OrdinalIgnoreCase)) { return false; } Transform parent2 = parent.parent; if ((Object)(object)parent2 == (Object)null || !((Object)parent2).name.StartsWith("Beaker", StringComparison.OrdinalIgnoreCase)) { return false; } Transform val = parent2; while ((Object)(object)val != (Object)null) { if (((Object)val).name != null && ((Object)val).name.IndexOf("ChemistryStation", StringComparison.OrdinalIgnoreCase) >= 0) { return true; } val = val.parent; } return false; } private static void CachePourablePrefab(string additiveId, string pourablePath) { if (!_pourablePrefabs.ContainsKey(additiveId)) { GameObject val = Resources.Load<GameObject>(pourablePath); if ((Object)(object)val != (Object)null) { _pourablePrefabs[additiveId] = val; } else { MelonLogger.Warning("Could not load pourable prefab for " + additiveId + " at " + pourablePath); } } } private static Transform? FindStationItemBottleContainer(StationItem stationItem) { Transform val = ((Component)stationItem).transform.Find("Pourable"); if ((Object)(object)val == (Object)null) { return null; } Transform result = null; int childCount = val.childCount; for (int i = 0; i < childCount; i++) { Transform child = val.GetChild(i); if ((Object)(object)child != (Object)null && ((Object)child).name.IndexOf("Bottle", StringComparison.OrdinalIgnoreCase) >= 0) { result = child; break; } } return result; } private static void SwapBottleMeshesAndMaterials(GameObject templatePrefab, Transform targetRoot) { MeshFilter[] componentsInChildren = templatePrefab.GetComponentsInChildren<MeshFilter>(true); MeshFilter[] componentsInChildren2 = ((Component)targetRoot).GetComponentsInChildren<MeshFilter>(true); foreach (MeshFilter val in componentsInChildren2) { if ((Object)(object)val == (Object)null) { continue; } string text = ((Object)val).name.ToLowerInvariant(); MeshFilter[] array = componentsInChildren; foreach (MeshFilter val2 in array) { if ((Object)(object)val2 == (Object)null) { continue; } string text2 = ((Object)val2).name.ToLowerInvariant(); if ((text.Contains("body") && text2.Contains("body")) || (text.Contains("label") && text2.Contains("label")) || (text.Contains("lid") && text2.Contains("lid"))) { val.sharedMesh = val2.sharedMesh; MeshRenderer component = ((Component)val).GetComponent<MeshRenderer>(); MeshRenderer component2 = ((Component)val2).GetComponent<MeshRenderer>(); if ((Object)(object)component != (Object)null && (Object)(object)component2 != (Object)null) { ((Renderer)component).sharedMaterials = ((Renderer)component2).sharedMaterials; } break; } } } } private static void ApplySuperGrowMaterialsToRenderers(Renderer[]? renderers) { SuperGrowVisuals.ApplySuperGrowMaterialsToRenderers(renderers); } private static void SetupAdditiveStationItem(string additiveId, StationItem templateStationItem) { ItemDefinition item = Registry.GetItem(additiveId); StorableItemDefinition val = (StorableItemDefinition)(object)((item is StorableItemDefinition) ? item : null); if ((Object)(object)val == (Object)null) { MelonLogger.Warning("Could not find additive: " + additiveId); } else if (!((Object)(object)val.StationItem != (Object)null)) { val.StationItem = templateStationItem; } } private static void SwapTrashItemVisualsById(string id, TrashItem trashItem) { if ((Object)(object)trashItem == (Object)null || string.IsNullOrEmpty(id)) { return; } bool flag = id == "supergrow"; if (!flag && id != "pgr" && id != "speedgrow" && id != "fertilizer") { return; } GameObject value = null; if (flag) { _pourablePrefabs.TryGetValue("pgr", out value); } else { _pourablePrefabs.TryGetValue(id, out value); } if ((Object)(object)value == (Object)null) { return; } try { if (!((Object)(object)((Component)trashItem).transform == (Object)null)) { SwapBottleMeshesAndMaterials(value, ((Component)trashItem).transform); if (flag) { ApplySuperGrowMaterialsToRenderers(((Component)trashItem).GetComponentsInChildren<Renderer>(true)); } } } catch (Exception ex) { MelonLogger.Error("Failed to swap trash visuals for " + id + ": " + ex.Message); MelonLogger.Error(ex.StackTrace); } } private static void SwapStationItemVisualsById(string id, StationItem stationItem) { //IL_0113: Unknown result type (might be due to invalid IL or missing references) //IL_011d: Unknown result type (might be due to invalid IL or missing references) //IL_0151: Unknown result type (might be due to invalid IL or missing references) //IL_0153: Unknown result type (might be due to invalid IL or missing references) //IL_0159: Unknown result type (might be due to invalid IL or missing references) //IL_015b: Unknown result type (might be due to invalid IL or missing references) //IL_0162: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)stationItem == (Object)null || string.IsNullOrEmpty(id)) { return; } bool flag = id == "supergrow"; if (!flag && id != "pgr" && id != "speedgrow" && id != "fertilizer") { return; } GameObject value = null; if (flag) { _pourablePrefabs.TryGetValue("pgr", out value); } else { _pourablePrefabs.TryGetValue(id, out value); } if ((Object)(object)value == (Object)null) { return; } try { Transform val = FindStationItemBottleContainer(stationItem); if ((Object)(object)val == (Object)null) { return; } SwapBottleMeshesAndMaterials(value, val); if (flag) { ApplySuperGrowMaterialsToRenderers(((Component)val).GetComponentsInChildren<Renderer>(true)); } object obj; if (!((Object)(object)((Component)stationItem).transform != (Object)null)) { obj = null; } else { Transform obj2 = ((Component)stationItem).transform.Find("Pourable"); obj = ((obj2 != null) ? ((Component)obj2).GetComponent<PourableModule>() : null); } PourableModule val2 = (PourableModule)obj; if ((Object)(object)val2 != (Object)null && (Object)(object)val2.LiquidContainer != (Object)null) { LiquidContainer liquidContainer = val2.LiquidContainer; if ((Object)(object)liquidContainer.LiquidVolume != (Object)null) { Transform transform = ((Component)liquidContainer.LiquidVolume).transform; transform.localScale *= 0.65f; } liquidContainer.MaxLevel *= 0.65f; if (_additiveColors.TryGetValue(id, out var value2)) { val2.LiquidType = id; val2.LiquidColor = value2; val2.PourParticlesColor = value2; liquidContainer.SetLiquidColor(value2, true, true); } } if (flag) { return; } switch (id) { case "pgr": case "speedgrow": case "fertilizer": { if (TryGetMonoBottleTrashPrefab(id, out TrashItem prefab)) { stationItem.TrashPrefab = prefab; } break; } } } catch (Exception ex) { MelonLogger.Error("Failed to swap station item visuals for " + id + ": " + ex.Message); MelonLogger.Error(ex.StackTrace); } } private static void SwapStationItemVisualsById(string id, StationItem stationItem, StorableItemDefinition itemDef) { if (!((Object)(object)stationItem == (Object)null) && !((Object)(object)itemDef == (Object)null)) { SwapStationItemVisualsById(id, stationItem); } } private static void SwapStationItemVisuals(StationItem stationItem, StorableItemDefinition itemDef) { SwapStationItemVisualsById(((ItemDefinition)itemDef).ID, stationItem, itemDef); } [HarmonyPatch(typeof(StationItem), "Initialize")] [HarmonyPostfix] private static void StationItem_Initialize_Postfix(StationItem __instance, StorableItemDefinition itemDefinition) { SwapStationItemVisuals(__instance, itemDefinition); } } [HarmonyPatch] internal static class GrowContainerPatches { private const string SuperGrowBottleTrashId = "supergrow_bottle"; private static bool _loggedGrowContainerTrashPrefabAssignException; private static readonly Vector3 HiddenPrefabPosition = new Vector3(100000f, 100000f, 100000f); private static Pourable? _superGrowPourablePrefab; private static int _removeItemDepth; private static bool _shouldReskinNextTrashSpawn; private static readonly HashSet<string> _loggedReskinnedTrashIds = new HashSet<string>(StringComparer.OrdinalIgnoreCase); private static void InjectSuperGrowIntoAllowedAdditives(GrowContainer container) { try { ItemDefinition item = Registry.GetItem("supergrow"); AdditiveDefinition val = (AdditiveDefinition)(object)((item is AdditiveDefinition) ? item : null); if ((Object)(object)val == (Object)null) { return; } if (container.AllowedAdditives != null) { AdditiveDefinition[] allowedAdditives = container.AllowedAdditives; foreach (AdditiveDefinition val2 in allowedAdditives) { if ((Object)(object)val2 != (Object)null && ((ItemDefinition)val2).ID == "supergrow") { return; } } } AdditiveDefinition[] obj = container.AllowedAdditives ?? Array.Empty<AdditiveDefinition>(); AdditiveDefinition[] array = (AdditiveDefinition[])(object)new AdditiveDefinition[obj.Length + 1]; obj.CopyTo(array, 0); array[^1] = val; container.AllowedAdditives = array; } catch (Exception ex) { MelonLogger.Error("Failed to inject SuperGrow into AllowedAdditives: " + ex.Message); } } [HarmonyPatch(typeof(GrowContainer), "InitializeGridItem")] [HarmonyPrefix] private static void GrowContainer_InitializeGridItem_Prefix(GrowContainer __instance) { InjectSuperGrowIntoAllowedAdditives(__instance); } private static Pourable? GetOrCreateSuperGrowPourablePrefab(Pourable basePrefab) { //IL_006a: Unknown result type (might be due to invalid IL or missing references) //IL_00b1: Unknown result type (might be due to invalid IL or missing references) //IL_00b6: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Unknown result type (might be due to invalid IL or missing references) //IL_00e1: 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) //IL_00ea: Unknown result type (might be due to invalid IL or missing references) if ((Object)(object)_superGrowPourablePrefab != (Object)null && (Object)(object)((Component)_superGrowPourablePrefab).gameObject != (Object)null) { return _superGrowPourablePrefab; } if ((Object)(object)basePrefab == (Object)null || (Object)(object)((Component)basePrefab).gameObject == (Object)null) { return null; } try { GameObject val = Object.Instantiate<GameObject>(((Component)basePrefab).gameObject); ((Object)val).name = "SuperGrow_PourablePrefab"; ((Object)val).hideFlags = (HideFlags)61; Object.DontDestroyOnLoad((Object)(object)val); val.transform.position = HiddenPrefabPosition; if (!val.activeSelf) { val.SetActive(true); } Pourable component = val.GetComponent<Pourable>(); if ((Object)(object)component == (Object)null) { Object.Destroy((Object)(object)val); return null; } PourableAdditive component2 = val.GetComponent<PourableAdditive>(); if ((Object)(object)component2 != (Object)null) { component2.LiquidColor = SuperGrowVisuals.PourColor; } ParticleSystem[] componentsInChildren = val.GetComponentsInChildren<ParticleSystem>(true); foreach (ParticleSystem val2 in componentsInChildren) { if (!((Object)(object)val2 == (Object)null)) { MainModule main = val2.main; ((MainModule)(ref main)).startColor = MinMaxGradient.op_Implicit(SuperGrowVisuals.PourColor); } } SuperGrowVisuals.ApplySuperGrowMaterialsToRenderers(val.GetComponentsInChildren<Renderer>(true)); try { TrashManager val3 = Object.FindObjectOfType<TrashManager>(); if ((Object)(object)val3 != (Object)null) { TrashItem trashPrefab = val3.GetTrashPrefab("supergrow_bottle"); if ((Object)(object)trashPrefab != (Object)null) { component.TrashItem = trashPrefab; } } } catch (Exception ex) { if (!_loggedGrowContainerTrashPrefabAssignException) { _loggedGrowContainerTrashPrefabAssignException = true; MelonLogger.Warning("Failed to assign SuperGrow trash prefab to grow-container pourable: " + ex.Message); MelonLogger.Warning(ex.StackTrace ?? "<no stack trace>"); } } _superGrowPourablePrefab = component; return _superGrowPourablePrefab; } catch (Exception ex2) { MelonLogger.Error("Failed to create SuperGrow pourable prefab: " + ex2.Message); MelonLogger.Error(ex2.StackTrace); return null; } } [HarmonyPatch(typeof(Equippable_Additive), "Equip")] [HarmonyPostfix] private static void Equippable_Additive_Equip_Postfix(Equippable_Additive __instance, ItemInstance item) { try { if (((item == null) ? null : item.Definition?.ID) != "supergrow") { return; } SuperGrowVisuals.ApplySuperGrowMaterialsToRenderers(((Component)__instance).GetComponentsInChildren<Renderer>(true)); Pourable pourablePrefab = ((Equippable_Pourable)__instance).PourablePrefab; if (!((Object)(object)pourablePrefab == (Object)null)) { Pourable orCreateSuperGrowPourablePrefab = GetOrCreateSuperGrowPourablePrefab(pourablePrefab); if ((Object)(object)orCreateSuperGrowPourablePrefab != (Object)null) { ((Equippable_Pourable)__instance).PourablePrefab = orCreateSuperGrowPourablePrefab; } } } catch (Exception ex) { MelonLogger.Error("Failed to apply SuperGrow grow-container pour visuals: " + ex.Message); MelonLogger.Error(ex.StackTrace); } } [HarmonyPatch(typeof(GrowContainerPourTask), "RemoveItem")] [HarmonyPrefix] private static void GrowContainerPourTask_RemoveItem_Prefix() { _removeItemDepth++; } [HarmonyPatch(typeof(GrowContainerPourTask), "RemoveItem")] [HarmonyFinalizer] private static void GrowContainerPourTask_RemoveItem_Finalizer(Exception __exception) { _removeItemDepth = Math.Max(0, _removeItemDepth - 1); _shouldReskinNextTrashSpawn = false; } [HarmonyPatch(typeof(PlayerInventory), "RemoveAmountOfItem")] [HarmonyPrefix] private static void PlayerInventory_RemoveAmountOfItem_Prefix(string ID) { if (_removeItemDepth > 0 && string.Equals(ID, "supergrow", StringComparison.OrdinalIgnoreCase)) { _shouldReskinNextTrashSpawn = true; } } [HarmonyPatch(typeof(TrashManager), "CreateAndReturnTrashItem")] [HarmonyPostfix] private static void TrashManager_CreateAndReturnTrashItem_Postfix_GrowContainerReskin(string id, object __result) { if (!_shouldReskinNextTrashSpawn) { return; } _shouldReskinNextTrashSpawn = false; try { if (__result != null) { object? obj = AccessTools.Property(__result.GetType(), "gameObject")?.GetValue(__result); GameObject val = (GameObject)((obj is GameObject) ? obj : null); if (!((Object)(object)val == (Object)null)) { SuperGrowVisuals.ApplySuperGrowMaterialsToRenderers(val.GetComponentsInChildren<Renderer>(true)); } } } catch (Exception ex) { MelonLogger.Error("Failed to reskin grow-container trash for SuperGrow: " + ex.Message); MelonLogger.Error(ex.StackTrace); } } } } namespace SuperGrow.Features { internal static class SuperGrowCreator { private static AdditiveDefinition? _superGrowDefinition; private static bool _loggedMissingAdditiveTemplate; private static bool _loggedRegistryUnavailable; public static void CreateSuperGrowItem() { try { if (!((Object)(object)Registry.GetItem("supergrow") != (Object)null)) { CreateAdditiveDefinition(); _ = (Object)(object)Registry.GetItem("supergrow") != (Object)null; } } catch (Exception ex) { MelonLogger.Error("Failed to create SuperGrow item: " + ex.Message); MelonLogger.Error(ex.StackTrace); } } private static void CreateAdditiveDefinition() { //IL_017f: Unknown result type (might be due to invalid IL or missing references) //IL_0184: Unknown result type (might be due to invalid IL or missing references) //IL_01ef: Unknown result type (might be due to invalid IL or missing references) //IL_01f4: Unknown result type (might be due to invalid IL or missing references) //IL_023f: Unknown result type (might be due to invalid IL or missing references) //IL_0244: Unknown result type (might be due to invalid IL or missing references) //IL_02b4: Unknown result type (might be due to invalid IL or missing references) //IL_02b9: Unknown result type (might be due to invalid IL or missing references) //IL_02ce: Unknown result type (might be due to invalid IL or missing references) //IL_02da: Expected O, but got Unknown if (!Singleton<Registry>.InstanceExists && !_loggedRegistryUnavailable) { _loggedRegistryUnavailable = true; MelonLogger.Warning("Registry singleton is not available yet; will retry"); } Registry val = Singleton<Registry>.Instance; if ((Object)(object)val == (Object)null) { val = Object.FindObjectOfType<Registry>(); } if ((Object)(object)val == (Object)null) { if (!_loggedRegistryUnavailable) { _loggedRegistryUnavailable = true; MelonLogger.Warning("Registry instance is not available; cannot add SuperGrow definition yet."); } return; } ItemDefinition item = Registry.GetItem("pgr"); AdditiveDefinition val2 = (AdditiveDefinition)(((object)((item is AdditiveDefinition) ? item : null)) ?? ((object)(/*isinst with value type is only supported in some contexts*/ ?? /*isinst with value type is only supported in some contexts*/))); if ((Object)(object)val2 == (Object)null) { if (!_loggedMissingAdditiveTemplate) { _loggedMissingAdditiveTemplate = true; ItemDefinition item2 = Registry.GetItem("pgr"); ItemDefinition item3 = Registry.GetItem("speedgrow"); ItemDefinition item4 = Registry.GetItem("fertilizer"); MelonLogger.Error("Could not find any existing additive to clone from!"); MelonLogger.Error("pgr=" + (((Object)(object)item2 == (Object)null) ? "<null>" : ((object)item2).GetType().FullName)); MelonLogger.Error("speedgrow=" + (((Object)(object)item3 == (Object)null) ? "<null>" : ((object)item3).GetType().FullName)); MelonLogger.Error("fertilizer=" + (((Object)(object)item4 == (Object)null) ? "<null>" : ((object)item4).GetType().FullName)); } return; } if ((Object)(object)_superGrowDefinition != (Object)null) { val.AddToRegistry((ItemDefinition)(object)_superGrowDefinition); return; } _superGrowDefinition = ScriptableObject.CreateInstance<AdditiveDefinition>(); ((ItemDefinition)_superGrowDefinition).Category = ((ItemDefinition)val2).Category; ((ItemDefinition)_superGrowDefinition).StackLimit = ((ItemDefinition)val2).StackLimit; ((ItemDefinition)_superGrowDefinition).Keywords = ((ItemDefinition)val2).Keywords; ((ItemDefinition)_superGrowDefinition).AvailableInDemo = ((ItemDefinition)val2).AvailableInDemo; ((ItemDefinition)_superGrowDefinition).UsableInFilters = ((ItemDefinition)val2).UsableInFilters; ((StorableItemDefinition)_superGrowDefinition).ResellMultiplier = ((StorableItemDefinition)val2).ResellMultiplier; ((StorableItemDefinition)_superGrowDefinition).ShopCategories = ((StorableItemDefinition)val2).ShopCategories; ((ItemDefinition)_superGrowDefinition).legalStatus = ((ItemDefinition)val2).legalStatus; ((ItemDefinition)_superGrowDefinition).Equippable = ((ItemDefinition)val2).Equippable; ((StorableItemDefinition)_superGrowDefinition).StoredItem = ((StorableItemDefinition)val2).StoredItem; ((StorableItemDefinition)_superGrowDefinition).StationItem = ((StorableItemDefinition)val2).StationItem; ((StorableItemDefinition)_superGrowDefinition).BasePurchasePrice = ((StorableItemDefinition)val2).BasePurchasePrice; ((ItemDefinition)_superGrowDefinition).LabelDisplayColor = ((ItemDefinition)val2).LabelDisplayColor; ((ItemDefinition)_superGrowDefinition).ID = "supergrow"; ((ItemDefinition)_superGrowDefinition).Name = "SuperGrow"; ((ItemDefinition)_superGrowDefinition).Description = "A powerful growth enhancer combining the effects of PGR, Speed Grow, and Fertilizer. Apply to plants for increased yield, faster growth, and improved quality."; ((Object)_superGrowDefinition).name = "SuperGrow"; Sprite iconSprite = SuperGrowAssets.GetIconSprite(); ((ItemDefinition)_superGrowDefinition).Icon = iconSprite ?? ((ItemDefinition)val2).Icon; if ((Object)(object)val2.DisplayMaterial != (Object)null) { Material value = new Material(val2.DisplayMaterial) { color = new Color(0.3f, 0.9f, 0.3f, 1f) }; SetPrivateProperty(_superGrowDefinition, "DisplayMaterial", value); } SetPrivateProperty(_superGrowDefinition, "QualityChange", SuperGrowSettings.QualityChange.Value); SetPrivateProperty(_superGrowDefinition, "YieldMultiplier", SuperGrowSettings.YieldMultiplier.Value); SetPrivateProperty(_superGrowDefinition, "InstantGrowth", SuperGrowSettings.InstantGrowth.Value); val.AddToRegistry((ItemDefinition)(object)_superGrowDefinition); } private static void SetPrivateProperty(object obj, string propertyName, object value) { Type type = obj.GetType(); FieldInfo field = type.GetField("<" + propertyName + ">k__BackingField", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { field.SetValue(obj, value); return; } PropertyInfo property = type.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic); if (property != null && property.CanWrite) { property.SetValue(obj, value); } else { MelonLogger.Warning("Could not set property " + propertyName + " on " + type.Name); } } } }