Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of HeavenlyPseudo v1.0.0
HeavenlyPseudo-IL2CPP.dll
Decompiled a week agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using HeavenlyPseudo; using HeavenlyPseudo.Helpers; using Il2CppFishNet; using Il2CppInterop.Runtime; using Il2CppInterop.Runtime.InteropTypes; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne; using Il2CppScheduleOne.Core.Items.Framework; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.PlayerScripts; using Il2CppScheduleOne.StationFramework; using Il2CppScheduleOne.UI.Stations; using Il2CppSystem; using Il2CppSystem.Collections.Generic; using MelonLoader; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using S1API.Items; using S1API.Items.Quality; using S1API.Items.Storable; using S1API.Leveling; using S1API.Products; using S1API.Stations; using Semver; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(global::HeavenlyPseudo.HeavenlyPseudo), "HeavenlyPseudo", "1.0.0", "k073l", null)] [assembly: MelonColor(1, 153, 153, 255)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: MelonPlatformDomain(/*Could not decode attribute arguments.*/)] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("HeavenlyPseudo-IL2CPP")] [assembly: AssemblyConfiguration("IL2CPP")] [assembly: AssemblyDescription("Adds Heavenly-Quality Pseudo")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+dc69da392536467e3a92d4d9285c76bf282e6e3b")] [assembly: AssemblyProduct("HeavenlyPseudo-IL2CPP")] [assembly: AssemblyTitle("HeavenlyPseudo-IL2CPP")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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 HeavenlyPseudo { public class DependenciesChecker { public class MissingDependencyInfo(string name, string version, List<DependencyUrl> urls, bool isRequired, string reason) { public string Name { get; set; } = name; public string Version { get; set; } = version; public List<DependencyUrl> Urls { get; set; } = urls; public bool IsRequired { get; set; } = isRequired; public string Reason { get; set; } = reason; } private static readonly Logger Logger = new Logger("DependenciesChecker"); private readonly List<DependencyInfo> _dependencies = new List<DependencyInfo>(); private List<MissingDependencyInfo> _missingDependencies = new List<MissingDependencyInfo>(); public bool ShowMenuBanner { get; set; } = true; public bool ShowBannerIfOptionalOnly { get; set; } = false; public bool UnloadIfMissingRequired { get; set; } = false; public void AddDependency(DependencyInfo dependency) { _dependencies.Add(dependency); } public void ProcessAndAlert() { CheckDependencies(); if (_missingDependencies.Count != 0) { PrintMissing(); if (ShowMenuBanner) { ShowBanner(); } MelonCoroutines.Start(DelayedUnload()); } } private void CheckDependencies() { _missingDependencies = new List<MissingDependencyInfo>(); foreach (DependencyInfo dependency in _dependencies) { MissingDependencyInfo missingDependencyInfo = IsPresent(dependency); if (missingDependencyInfo != null) { _missingDependencies.Add(missingDependencyInfo); } } } private void PrintMissing() { Logger.Msg("Missing dependencies:"); foreach (MissingDependencyInfo missingDependency in _missingDependencies) { if (missingDependency.IsRequired) { Logger.Error($"- {missingDependency.Name} (min version {missingDependency.Version}): required - {missingDependency.Reason}"); } else { Logger.Warning($"- {missingDependency.Name} (min version {missingDependency.Version}): optional - {missingDependency.Reason}"); } if (missingDependency.Urls.Count == 0) { continue; } Logger.Msg(" Possible sources:"); foreach (DependencyUrl url in missingDependency.Urls) { Logger.Msg(" - " + url.SourceName + ": " + url.Url); } } } private void ShowBanner() { ((MelonEventBase<LemonAction<int, string>>)(object)MelonEvents.OnSceneWasLoaded).Subscribe((LemonAction<int, string>)delegate(int _, string name) { if (!(name != "Menu")) { MissingDepsPanelCreator.Show(this, _missingDependencies); } }, 0, false); ((MelonEventBase<LemonAction<int, string>>)(object)MelonEvents.OnSceneWasUnloaded).Subscribe((LemonAction<int, string>)delegate(int _, string name) { if (!(name != "Menu")) { MissingDepsPanelCreator.Hide(); } }, 0, false); MissingDepsPanelCreator.Show(this, _missingDependencies); } private IEnumerator DelayedUnload() { yield return (object)new WaitForSeconds(5f); if (UnloadIfMissingRequired && _missingDependencies.Any((MissingDependencyInfo d) => d.IsRequired)) { Logger.Warning("Missing required dependencies detected and UnloadIfMissingRequired is true, unloading mod."); ((MelonBase)Melon<HeavenlyPseudo>.Instance).Unregister("Missing required dependencies", false); } } private static MissingDependencyInfo? IsPresent(DependencyInfo dependency) { Assembly foundInDomain = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly assembly) => assembly.GetName().Name == dependency.AssemblyName); if (foundInDomain == null) { Logger.Debug(dependency.AssemblyName + " not found in AppDomain, marking as missing."); return new MissingDependencyInfo(dependency.Name, dependency.Version, dependency.Urls, dependency.IsRequired, "Assembly not found"); } MelonMod val = ((IEnumerable<MelonMod>)MelonTypeBase<MelonMod>.RegisteredMelons).FirstOrDefault((Func<MelonMod, bool>)((MelonMod m) => ((MelonBase)m).MelonAssembly.Assembly == foundInDomain)); if (val == null) { Logger.Debug(foundInDomain.GetName().Name + " wasn't found in RegisteredMelons."); Version version = foundInDomain.GetName().Version; if (version == null) { Logger.Debug(dependency.AssemblyName + " version is not available."); return new MissingDependencyInfo(dependency.Name, dependency.Version, dependency.Urls, dependency.IsRequired, "Cannot verify version"); } if (!Version.TryParse(dependency.Version, out Version result)) { Logger.Debug(dependency.AssemblyName + " version is not a valid version."); return new MissingDependencyInfo(dependency.Name, dependency.Version, dependency.Urls, dependency.IsRequired, "Invalid version format"); } if (version < result) { Logger.Debug(dependency.AssemblyName + " version is too old."); return new MissingDependencyInfo(dependency.Name, dependency.Version, dependency.Urls, dependency.IsRequired, $"Version {version} found, but {dependency.Version} required"); } return null; } SemVersion semanticVersion = ((MelonBase)val).Info.SemanticVersion; if (semanticVersion == (SemVersion)null) { Logger.Debug($"{foundInDomain.GetName().Name}'s version {semanticVersion} is not SemVer."); if (!Version.TryParse(dependency.Version, out Version result2)) { Logger.Debug(dependency.AssemblyName + " version is not a valid version."); return new MissingDependencyInfo(dependency.Name, dependency.Version, dependency.Urls, dependency.IsRequired, "Invalid version format"); } if (!Version.TryParse(((MelonBase)val).Info.Version, out Version result3)) { Logger.Debug(dependency.AssemblyName + " version is not a valid version."); return new MissingDependencyInfo(dependency.Name, dependency.Version, dependency.Urls, dependency.IsRequired, "Invalid version format"); } if (result3 < result2) { Logger.Debug(dependency.AssemblyName + " version is too old."); return new MissingDependencyInfo(dependency.Name, dependency.Version, dependency.Urls, dependency.IsRequired, $"Version {result3} found, but {dependency.Version} required"); } return null; } SemVersion val2 = default(SemVersion); if (!SemVersion.TryParse(dependency.Version, ref val2, false)) { Logger.Debug(dependency.AssemblyName + " version is not a valid version."); return new MissingDependencyInfo(dependency.Name, dependency.Version, dependency.Urls, dependency.IsRequired, "Invalid version format"); } if (semanticVersion < val2) { Logger.Debug(dependency.AssemblyName + " version is too old."); return new MissingDependencyInfo(dependency.Name, dependency.Version, dependency.Urls, dependency.IsRequired, $"Version {semanticVersion} found, but {dependency.Version} required"); } return null; } } public class DependencyInfo { public string Name { get; set; } public string AssemblyName { get; set; } public string Version { get; set; } public bool IsRequired { get; set; } public List<DependencyUrl> Urls { get; set; } public DependencyInfo(string name, string version, string? assemblyName = null, List<DependencyUrl>? urls = null, bool isRequired = true) { Name = name; AssemblyName = assemblyName ?? name; Version = version; IsRequired = isRequired; Urls = urls ?? new List<DependencyUrl>(); } public DependencyInfo() { } } public class DependencyUrl { public string SourceName { get; set; } public string Url { get; set; } public DependencyUrl(string sourceName, string url) { SourceName = sourceName; Url = url; } public DependencyUrl() { } } internal static class MissingDepsPanelCreator { private static GameObject? _canvasObject; public static void Show(DependenciesChecker instance, List<DependenciesChecker.MissingDependencyInfo> deps) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Expected O, but got Unknown //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Expected O, but got Unknown //IL_0319: Unknown result type (might be due to invalid IL or missing references) //IL_0303: Unknown result type (might be due to invalid IL or missing references) //IL_0350: Unknown result type (might be due to invalid IL or missing references) //IL_0357: Expected O, but got Unknown //IL_03c7: Unknown result type (might be due to invalid IL or missing references) Hide(); _canvasObject = new GameObject("MissingDependenciesCanvas"); Canvas val = _canvasObject.AddComponent<Canvas>(); val.renderMode = (RenderMode)0; val.sortingOrder = 9999; _canvasObject.AddComponent<GraphicRaycaster>(); GameObject val2 = new GameObject("MissingDependenciesPanel"); val2.transform.SetParent(_canvasObject.transform, false); RectTransform val3 = val2.AddComponent<RectTransform>(); val3.anchorMin = new Vector2(1f, 0.5f); val3.anchorMax = new Vector2(1f, 0.5f); val3.pivot = new Vector2(1f, 0.5f); val3.anchoredPosition = new Vector2(-20f, 0f); val3.sizeDelta = new Vector2(420f, 0f); Image val4 = val2.AddComponent<Image>(); ((Graphic)val4).color = new Color(0.08f, 0.08f, 0.08f, 0.95f); ContentSizeFitter val5 = val2.AddComponent<ContentSizeFitter>(); val5.verticalFit = (FitMode)2; VerticalLayoutGroup val6 = val2.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)val6).padding = new RectOffset(16, 16, 12, 12); ((HorizontalOrVerticalLayoutGroup)val6).spacing = 6f; ((LayoutGroup)val6).childAlignment = (TextAnchor)0; ((HorizontalOrVerticalLayoutGroup)val6).childForceExpandWidth = true; GameObject val7 = new GameObject("Header"); val7.transform.SetParent(val2.transform, false); Text val8 = val7.AddComponent<Text>(); val8.text = "Missing Dependencies"; val8.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); val8.fontSize = 18; val8.fontStyle = (FontStyle)1; ((Graphic)val8).color = Color.white; val8.alignment = (TextAnchor)3; if (deps.All((DependenciesChecker.MissingDependencyInfo d) => !d.IsRequired) && !instance.ShowBannerIfOptionalOnly) { Hide(); return; } foreach (DependenciesChecker.MissingDependencyInfo dep in deps) { GameObject val9 = new GameObject("Dep_" + dep.Name); val9.transform.SetParent(val2.transform, false); val9.AddComponent<LayoutElement>().minHeight = 20f; Text val10 = val9.AddComponent<Text>(); val10.text = $" {dep.Name} (min v{dep.Version}) - {dep.Reason}"; val10.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); val10.fontSize = 15; ((Graphic)val10).color = (dep.IsRequired ? new Color(1f, 0.4f, 0.4f) : new Color(1f, 0.8f, 0.3f)); val10.alignment = (TextAnchor)0; } GameObject val11 = new GameObject("Footer"); val11.transform.SetParent(val2.transform, false); Text val12 = val11.AddComponent<Text>(); val12.text = "See the console (or log at " + Path.Combine(MelonEnvironment.MelonLoaderLogsDirectory, "Latest.log") + ") for details."; val12.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); val12.fontSize = 14; ((Graphic)val12).color = new Color(0.6f, 0.6f, 0.6f); val12.alignment = (TextAnchor)0; } public static void Hide() { if ((Object)(object)_canvasObject != (Object)null) { Object.Destroy((Object)(object)_canvasObject); _canvasObject = null; } } } public class Logger { private static bool _initialized; private static MethodInfo? _passLogMsgNew; private static MethodInfo? _passLogMsgLegacy; private static MethodInfo? _runMsgCallbacks; private static MethodInfo? _warningMethod; private static MethodInfo? _runWarningCallbacks; private static MethodInfo? _passLogError; private static MethodInfo? _runErrorCallbacks; private static object? _defaultTextColor; private static Func<object>? _getNsColor; public string? Namesection { get; set; } public bool RaiseTrace { get; set; } public bool RaiseDebug { get; set; } public Logger(string? namesection = null) { Namesection = namesection; } public Logger(Instance melonLogger) { FieldInfo field = typeof(Instance).GetField("Name", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { Namesection = field.GetValue(melonLogger) as string; } } public void Trace(params object[] args) { Log(LogLevel.Trace, null, args); } public void Debug(params object[] args) { Log(LogLevel.Debug, null, args); } public void T(params object[] args) { Log(LogLevel.Trace, null, args); } public void D(params object[] args) { Log(LogLevel.Debug, null, args); } public void Info(params object[] args) { Log(LogLevel.Info, null, args); } public void Msg(params object[] args) { Log(LogLevel.Info, null, args); } public void I(params object[] args) { Log(LogLevel.Info, null, args); } public void M(params object[] args) { Log(LogLevel.Info, null, args); } public void Warning(params object[] args) { Log(LogLevel.Warning, null, args); } public void Warn(params object[] args) { Log(LogLevel.Warning, null, args); } public void W(params object[] args) { Log(LogLevel.Warning, null, args); } public void Error(params object[] args) { Log(LogLevel.Error, null, args); } public void Err(params object[] args) { Log(LogLevel.Error, null, args); } public void E(params object[] args) { Log(LogLevel.Error, null, args); } public void Fatal(params object[] args) { Log(LogLevel.BigError, null, args); } public void BigError(params object[] args) { Log(LogLevel.BigError, null, args); } public void F(params object[] args) { Log(LogLevel.BigError, null, args); } public void BE(params object[] args) { Log(LogLevel.BigError, null, args); } public void InfoColored(object txtColor, params object[] args) { Log(LogLevel.Info, txtColor, args); } public void MsgColored(object txtColor, params object[] args) { Log(LogLevel.Info, txtColor, args); } public void IC(object txtColor, params object[] args) { Log(LogLevel.Info, txtColor, args); } public void MC(object txtColor, params object[] args) { Log(LogLevel.Info, txtColor, args); } private static void EnsureInitialized() { if (_initialized) { return; } Type typeFromHandle = typeof(MelonLogger); FieldInfo field = typeFromHandle.GetField("DefaultTextColor", BindingFlags.Static | BindingFlags.Public); if (field == null) { return; } Type fieldType = field.FieldType; _defaultTextColor = field.GetValue(null); BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.NonPublic; _passLogMsgNew = typeFromHandle.GetMethod("PassLogMsg", bindingAttr, null, new Type[5] { fieldType, typeof(string), fieldType, typeof(string), typeof(string) }, null); if (_passLogMsgNew == null) { _passLogMsgLegacy = typeFromHandle.GetMethod("PastelMsg", bindingAttr, null, new Type[4] { fieldType, fieldType, typeof(string), typeof(string) }, null); } _runMsgCallbacks = typeFromHandle.GetMethod("RunMsgCallbacks", bindingAttr, null, new Type[4] { fieldType, fieldType, typeof(string), typeof(string) }, null); _passLogError = typeFromHandle.GetMethod("PassLogError", bindingAttr, null, new Type[3] { typeof(string), typeof(string), typeof(bool) }, null); _runErrorCallbacks = typeFromHandle.GetMethod("RunErrorCallbacks", bindingAttr, null, new Type[2] { typeof(string), typeof(string) }, null); _runWarningCallbacks = typeFromHandle.GetMethod("RunWarningCallbacks", bindingAttr, null, new Type[2] { typeof(string), typeof(string) }, null); BindingFlags bindingAttr2 = BindingFlags.Static | BindingFlags.Public; _warningMethod = typeFromHandle.GetMethod("Warning", bindingAttr2, null, new Type[2] { typeof(string), typeof(string) }, null) ?? typeFromHandle.GetMethod("Warning", bindingAttr, null, new Type[2] { typeof(string), typeof(string) }, null); Type type = typeof(Melon<>).MakeGenericType(typeof(HeavenlyPseudo)); PropertyInfo instanceProp = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public); if (instanceProp != null) { PropertyInfo consoleColorProp = instanceProp.PropertyType.GetProperty("ConsoleColor", BindingFlags.Instance | BindingFlags.Public); if (consoleColorProp != null) { _getNsColor = () => consoleColorProp.GetValue(instanceProp.GetValue(null)); } } if (_getNsColor == null) { _getNsColor = () => _defaultTextColor; } _initialized = true; } private static void PassLogMsg(object txtColor, string message, object nsColor, string ns) { if (_passLogMsgNew != null) { _passLogMsgNew.Invoke(null, new object[5] { txtColor, message, nsColor, ns, null }); } else if (_passLogMsgLegacy != null) { _passLogMsgLegacy.Invoke(null, new object[4] { nsColor, txtColor, ns, message }); } } private static string GetCallerInfo() { StackTrace stackTrace = new StackTrace(); for (int i = 2; i < stackTrace.FrameCount; i++) { StackFrame frame = stackTrace.GetFrame(i); MethodBase method = frame.GetMethod(); if (method?.DeclaringType != null) { return method.DeclaringType.FullName + "." + method.Name; } } return "unknown"; } private void Log(LogLevel level, object? txtColor, params object[] args) { if (args.Length == 0) { return; } string text; if (args.Length == 1) { text = args[0]?.ToString() ?? ""; } else { string format = args[0]?.ToString() ?? ""; text = string.Format(format, args.Skip(1).ToArray()); } string text2 = (string.IsNullOrWhiteSpace(Namesection) ? "HeavenlyPseudo" : ("HeavenlyPseudo." + Namesection)); EnsureInitialized(); object obj = _getNsColor(); object obj2 = txtColor ?? _defaultTextColor; switch (level) { case LogLevel.Trace: { string text3 = "[TRACE " + GetCallerInfo() + "] " + text; if (RaiseTrace) { PassLogMsg(obj2, text3, obj, text2); _runMsgCallbacks?.Invoke(null, new object[4] { obj, obj2, text3, text2 }); } else { MelonDebug.Msg(text3); } break; } case LogLevel.Debug: { string text4 = "[DEBUG " + GetCallerInfo() + "] " + text; if (RaiseDebug) { PassLogMsg(obj2, text4, obj, text2); _runMsgCallbacks?.Invoke(null, new object[4] { obj, obj2, text4, text2 }); } else { MelonDebug.Msg(text4); } break; } case LogLevel.Info: PassLogMsg(obj2, text, obj, text2); _runMsgCallbacks?.Invoke(null, new object[4] { obj, obj2, text2, text }); break; case LogLevel.Warning: _warningMethod?.Invoke(null, new object[2] { text2, text }); _runWarningCallbacks?.Invoke(null, new object[2] { text2, text }); break; case LogLevel.Error: _passLogError?.Invoke(null, new object[3] { text, text2, false }); _runErrorCallbacks?.Invoke(null, new object[2] { text2, text }); break; case LogLevel.BigError: MelonLogger.BigError(text2, text); break; } } } public enum LogLevel { Trace, Debug, Info, Warning, Error, BigError } public static class BuildInfo { public const string Name = "HeavenlyPseudo"; public const string Description = "Adds Heavenly-Quality Pseudo"; public const string Author = "k073l"; public const string Version = "1.0.0"; } public class HeavenlyPseudo : MelonMod { private static Logger Logger; public override void OnInitializeMelon() { Logger = new Logger(); Logger.Msg("HeavenlyPseudo initialized"); CheckDependencies(); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { try { PseudoCreator pseudoCreator = new PseudoCreator(); pseudoCreator.CreateItem(sceneName); } catch (Exception ex) { Logger.E("Error while creating item: " + ex.Message); } } private static void CheckDependencies() { DependenciesChecker dependenciesChecker = new DependenciesChecker { ShowMenuBanner = true, UnloadIfMissingRequired = true }; dependenciesChecker.AddDependency(new DependencyInfo { Name = "S1API (Forked)", AssemblyName = "S1API", IsRequired = true, Version = "3.0.5", Urls = new List<DependencyUrl>(3) { new DependencyUrl { SourceName = "Thunderstore", Url = "https://thunderstore.io/c/schedule-i/p/ifBars/S1API_Forked/" }, new DependencyUrl { SourceName = "NexusMods", Url = "https://www.nexusmods.com/schedule1/mods/1194" }, new DependencyUrl { SourceName = "Github", Url = "https://github.com/ifBars/S1API/releases/" } } }); dependenciesChecker.ProcessAndAlert(); } } } namespace HeavenlyPseudo.Helpers { internal class PseudoCreator { private const string HighQualityPseudoID = "highqualitypseudo"; private const string FluMedicineID = "flumedicine"; private const string HeavenlyQualityPseudoID = "heavenlyqualitypseudo"; private const string TargetRecipeID = "1xliquidmeth"; private bool _itemsInitialized = false; private static readonly Logger Log = new Logger("PseudoCreator"); internal void CreateItem(string sceneName) { if (sceneName == "Main" && !_itemsInitialized) { InitializeItems(); _itemsInitialized = true; } } private void InitializeItems() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) Log.M("Creating heavenlyqualitypseudo item"); QualityItemDefinitionBuilder val = ((StorableItemDefinitionBuilderBase<QualityItemDefinitionBuilder>)(object)((StorableItemDefinitionBuilderBase<QualityItemDefinitionBuilder>)(object)((StorableItemDefinitionBuilderBase<QualityItemDefinitionBuilder>)(object)QualityItemCreator.CloneFrom("highqualitypseudo").WithDefaultQuality((Quality)4)).WithBasicInfo("heavenlyqualitypseudo", "Heavenly-Quality Pseudo", "Very high-quality pseudoephedrine in tablet form. A common precursor for meth.", (ItemCategory)9)).WithPricing(150f, 0.5f)).WithRequiredRank((FullRank?)new FullRank((Rank)5, 3)); val.Build(); MelonCoroutines.Start(Utils.WaitForPlayer(AddToChemRecipe())); } private void AddChemRecipe() { Log.M("Creating Chemistry Recipe for heavenlyqualitypseudo"); ChemistryStationRecipes.CreateAndRegister((Action<ChemistryStationRecipeBuilder>)delegate(ChemistryStationRecipeBuilder b) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) b.WithIngredient("highqualitypseudo", 1).WithIngredient("flumedicine", 1).WithProduct("heavenlyqualitypseudo", 1) .WithCalculationMethod((QualityCalculationMethod)1) .WithCookTimeMinutes(120) .WithTemperature(150f, 50f) .WithFinalLiquidColor(new Color(1f, 0.84f, 0f)) .WithTitle("Heavenly-Quality Pseudo"); }); } private IEnumerator AddToChemRecipe() { AddChemRecipe(); Log.M("Adding heavenlyqualitypseudo as valid ingredient for 1xliquidmeth"); ItemDefinition heavenlyPseudo = Registry.GetItem("heavenlyqualitypseudo"); Log.T("Adding to chem recipes"); yield return (object)new WaitUntil(Func<bool>.op_Implicit((Func<bool>)(() => Singleton<ChemistryStationCanvas>.InstanceExists))); StationRecipe lqMethRecipe = Singleton<ChemistryStationCanvas>.Instance.Recipes.AsEnumerable<StationRecipe>().FirstOrDefault((Func<StationRecipe, bool>)((StationRecipe r) => r.RecipeID == "1xliquidmeth")); Log.T("Recipe found, looking for the pseudo ingredient"); IngredientQuantity pseudoIngredient = ((lqMethRecipe != null) ? lqMethRecipe.Ingredients.AsEnumerable<IngredientQuantity>().FirstOrDefault((Func<IngredientQuantity, bool>)((IngredientQuantity i) => ((BaseItemDefinition)i.Item).ID == "pseudo")) : null); Log.T("Ingredient found, adding heavenly pseudo to it"); if (!Utils.Is<QualityItemDefinition>((object)heavenlyPseudo, out QualityItemDefinition heavenlyPseudoAsQuality)) { Log.E("Heavenly pseudo is not a quality item definition, cannot add to recipe ingredient!"); } else if (pseudoIngredient != null) { pseudoIngredient.Items.Add((ItemDefinition)(object)heavenlyPseudoAsQuality); } } } public static class Il2CppListExtensions { public static IEnumerable<T> AsEnumerable<T>(this List<T> list) { return list ?? new List<T>(); } public static object ToNativeList<T>(this List<T> source) { return source.ToIl2CppList(); } public static List<T> ToIl2CppList<T>(this IEnumerable<T> source) { List<T> val = new List<T>(); foreach (T item in source) { val.Add(item); } return val; } public static List<T> ConvertToList<T>(List<T> il2CppList) { List<T> list = new List<T>(); T[] collection = Il2CppArrayBase<T>.op_Implicit(il2CppList.ToArray()); list.AddRange(collection); return list; } public static IEnumerable<T> AsEnumerable<T>(this List<T> list) { IEnumerable<T> result; if (list != null) { result = ((IEnumerable<T>)list._items).Take(list._size); } else { IEnumerable<T> enumerable = Array.Empty<T>(); result = enumerable; } return result; } public static object ToNativeList<T>(this List<T> source) { return source; } } public static class Utils { private static readonly Instance Logger = new Instance("HeavenlyPseudo-Utils"); public static T? FindObjectByName<T>(string objectName) where T : Object { try { foreach (T item in Resources.FindObjectsOfTypeAll<T>()) { if (((Object)item).name != objectName) { continue; } return item; } return default(T); } catch (Exception ex) { Logger.Error($"Error finding {typeof(T).Name} '{objectName}': {ex.Message}"); return default(T); } } public static List<T> GetAllComponentsInChildrenRecursive<T>(GameObject obj) where T : Component { List<T> list = new List<T>(); if ((Object)(object)obj == (Object)null) { return list; } T[] array = Il2CppArrayBase<T>.op_Implicit(obj.GetComponents<T>()); if (array.Length != 0) { list.AddRange(array); } for (int i = 0; i < obj.transform.childCount; i++) { Transform child = obj.transform.GetChild(i); list.AddRange(GetAllComponentsInChildrenRecursive<T>(((Component)child).gameObject)); } return list; } public static bool Is<T>(object obj, out T? result) where T : Object { Object val = (Object)((obj is Object) ? obj : null); if (val != null) { Type val2 = Il2CppType.Of<T>(); Type il2CppType = val.GetIl2CppType(); if (val2.IsAssignableFrom(il2CppType)) { result = ((Il2CppObjectBase)val).TryCast<T>(); return result != null; } } result = default(T); return false; } public static IEnumerator WaitForPlayer(IEnumerator routine) { while ((Object)(object)Player.Local == (Object)null || (Object)(object)((Component)Player.Local).gameObject == (Object)null) { yield return null; } MelonCoroutines.Start(routine); } public static IEnumerator WaitForNetwork(IEnumerator routine) { while (!InstanceFinder.IsServer && !InstanceFinder.IsClient) { yield return null; } MelonCoroutines.Start(routine); } public static IEnumerator WaitForCondition(Func<bool> condition, float timeout = float.NaN, Action? onTimeout = null, Action? onFinish = null) { float startTime = Time.time; while (!condition()) { if (!float.IsNaN(timeout) && Time.time - startTime > timeout) { onTimeout?.Invoke(); yield break; } yield return null; } onFinish?.Invoke(); } public static string GetHierarchyPath(this Transform transform) { if ((Object)(object)transform == (Object)null) { return "null"; } string text = ((Object)transform).name; Transform parent = transform.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } public static T GetOrAddComponent<T>(this GameObject gameObject) where T : Component { T component = gameObject.GetComponent<T>(); if ((Object)(object)component != (Object)null) { return component; } return gameObject.AddComponent<T>(); } public static Material? DrawDebugVisuals(this GameObject gameObject, Color? color = null) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) Renderer component = gameObject.GetComponent<Renderer>(); if ((Object)(object)component == (Object)null) { Logger.Error("GameObject " + ((Object)gameObject).name + " has no Renderer component"); return null; } Color valueOrDefault = color.GetValueOrDefault(); if (!color.HasValue) { ((Color)(ref valueOrDefault))..ctor(1f, 0f, 1f, 0.5f); color = valueOrDefault; } Shader val = Shader.Find("Universal Render Pipeline/Lit"); if ((Object)(object)val == (Object)null) { return null; } Material val2 = new Material(val); if (val2.HasProperty("_Surface")) { val2.SetFloat("_Surface", 1f); } Color value = color.Value; if (value.a <= 0f) { value.a = 0.2f; } if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", value); } if (val2.HasProperty("_EmissionColor")) { val2.EnableKeyword("_EMISSION"); val2.SetColor("_EmissionColor", new Color(value.r, value.g, value.b) * 1.5f); } val2.SetInt("_ZWrite", 0); val2.renderQueue = 3000; Material material = component.material; component.material = val2; return material; } } }
HeavenlyPseudo-Mono.dll
Decompiled a week agousing System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using FishNet; using HeavenlyPseudo; using HeavenlyPseudo.Helpers; using MelonLoader; using MelonLoader.Utils; using Microsoft.CodeAnalysis; using S1API.Items; using S1API.Items.Quality; using S1API.Items.Storable; using S1API.Leveling; using S1API.Products; using S1API.Stations; using ScheduleOne; using ScheduleOne.Core.Items.Framework; using ScheduleOne.DevUtilities; using ScheduleOne.ItemFramework; using ScheduleOne.PlayerScripts; using ScheduleOne.StationFramework; using ScheduleOne.UI.Stations; using Semver; using UnityEngine; using UnityEngine.UI; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)] [assembly: MelonInfo(typeof(global::HeavenlyPseudo.HeavenlyPseudo), "HeavenlyPseudo", "1.0.0", "k073l", null)] [assembly: MelonColor(1, 153, 153, 255)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: MelonPlatformDomain(/*Could not decode attribute arguments.*/)] [assembly: TargetFramework(".NETStandard,Version=v2.1", FrameworkDisplayName = ".NET Standard 2.1")] [assembly: IgnoresAccessChecksTo("Assembly-CSharp")] [assembly: AssemblyCompany("HeavenlyPseudo-Mono")] [assembly: AssemblyConfiguration("Mono")] [assembly: AssemblyDescription("Adds Heavenly-Quality Pseudo")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+dc69da392536467e3a92d4d9285c76bf282e6e3b")] [assembly: AssemblyProduct("HeavenlyPseudo-Mono")] [assembly: AssemblyTitle("HeavenlyPseudo-Mono")] [assembly: SecurityPermission(SecurityAction.RequestMinimum, SkipVerification = true)] [assembly: AssemblyVersion("1.0.0.0")] [module: UnverifiableCode] [module: RefSafetyRules(11)] namespace Microsoft.CodeAnalysis { [CompilerGenerated] [Embedded] internal sealed class EmbeddedAttribute : Attribute { } } namespace System.Runtime.CompilerServices { [CompilerGenerated] [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] [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] [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 HeavenlyPseudo { public class DependenciesChecker { public class MissingDependencyInfo(string name, string version, List<DependencyUrl> urls, bool isRequired, string reason) { public string Name { get; set; } = name; public string Version { get; set; } = version; public List<DependencyUrl> Urls { get; set; } = urls; public bool IsRequired { get; set; } = isRequired; public string Reason { get; set; } = reason; } private static readonly Logger Logger = new Logger("DependenciesChecker"); private readonly List<DependencyInfo> _dependencies = new List<DependencyInfo>(); private List<MissingDependencyInfo> _missingDependencies = new List<MissingDependencyInfo>(); public bool ShowMenuBanner { get; set; } = true; public bool ShowBannerIfOptionalOnly { get; set; } = false; public bool UnloadIfMissingRequired { get; set; } = false; public void AddDependency(DependencyInfo dependency) { _dependencies.Add(dependency); } public void ProcessAndAlert() { CheckDependencies(); if (_missingDependencies.Count != 0) { PrintMissing(); if (ShowMenuBanner) { ShowBanner(); } MelonCoroutines.Start(DelayedUnload()); } } private void CheckDependencies() { _missingDependencies = new List<MissingDependencyInfo>(); foreach (DependencyInfo dependency in _dependencies) { MissingDependencyInfo missingDependencyInfo = IsPresent(dependency); if (missingDependencyInfo != null) { _missingDependencies.Add(missingDependencyInfo); } } } private void PrintMissing() { Logger.Msg("Missing dependencies:"); foreach (MissingDependencyInfo missingDependency in _missingDependencies) { if (missingDependency.IsRequired) { Logger.Error("- " + missingDependency.Name + " (min version " + missingDependency.Version + "): required - " + missingDependency.Reason); } else { Logger.Warning("- " + missingDependency.Name + " (min version " + missingDependency.Version + "): optional - " + missingDependency.Reason); } if (missingDependency.Urls.Count == 0) { continue; } Logger.Msg(" Possible sources:"); foreach (DependencyUrl url in missingDependency.Urls) { Logger.Msg(" - " + url.SourceName + ": " + url.Url); } } } private void ShowBanner() { ((MelonEventBase<LemonAction<int, string>>)(object)MelonEvents.OnSceneWasLoaded).Subscribe((LemonAction<int, string>)delegate(int _, string name) { if (!(name != "Menu")) { MissingDepsPanelCreator.Show(this, _missingDependencies); } }, 0, false); ((MelonEventBase<LemonAction<int, string>>)(object)MelonEvents.OnSceneWasUnloaded).Subscribe((LemonAction<int, string>)delegate(int _, string name) { if (!(name != "Menu")) { MissingDepsPanelCreator.Hide(); } }, 0, false); MissingDepsPanelCreator.Show(this, _missingDependencies); } private IEnumerator DelayedUnload() { yield return (object)new WaitForSeconds(5f); if (UnloadIfMissingRequired && _missingDependencies.Any((MissingDependencyInfo d) => d.IsRequired)) { Logger.Warning("Missing required dependencies detected and UnloadIfMissingRequired is true, unloading mod."); ((MelonBase)Melon<HeavenlyPseudo>.Instance).Unregister("Missing required dependencies", false); } } private static MissingDependencyInfo? IsPresent(DependencyInfo dependency) { Assembly foundInDomain = AppDomain.CurrentDomain.GetAssemblies().FirstOrDefault((Assembly assembly) => assembly.GetName().Name == dependency.AssemblyName); if (foundInDomain == null) { Logger.Debug(dependency.AssemblyName + " not found in AppDomain, marking as missing."); return new MissingDependencyInfo(dependency.Name, dependency.Version, dependency.Urls, dependency.IsRequired, "Assembly not found"); } MelonMod val = ((IEnumerable<MelonMod>)MelonTypeBase<MelonMod>.RegisteredMelons).FirstOrDefault((Func<MelonMod, bool>)((MelonMod m) => ((MelonBase)m).MelonAssembly.Assembly == foundInDomain)); if (val == null) { Logger.Debug(foundInDomain.GetName().Name + " wasn't found in RegisteredMelons."); Version version = foundInDomain.GetName().Version; if (version == null) { Logger.Debug(dependency.AssemblyName + " version is not available."); return new MissingDependencyInfo(dependency.Name, dependency.Version, dependency.Urls, dependency.IsRequired, "Cannot verify version"); } if (!Version.TryParse(dependency.Version, out Version result)) { Logger.Debug(dependency.AssemblyName + " version is not a valid version."); return new MissingDependencyInfo(dependency.Name, dependency.Version, dependency.Urls, dependency.IsRequired, "Invalid version format"); } if (version < result) { Logger.Debug(dependency.AssemblyName + " version is too old."); return new MissingDependencyInfo(dependency.Name, dependency.Version, dependency.Urls, dependency.IsRequired, $"Version {version} found, but {dependency.Version} required"); } return null; } SemVersion semanticVersion = ((MelonBase)val).Info.SemanticVersion; if (semanticVersion == (SemVersion)null) { Logger.Debug($"{foundInDomain.GetName().Name}'s version {semanticVersion} is not SemVer."); if (!Version.TryParse(dependency.Version, out Version result2)) { Logger.Debug(dependency.AssemblyName + " version is not a valid version."); return new MissingDependencyInfo(dependency.Name, dependency.Version, dependency.Urls, dependency.IsRequired, "Invalid version format"); } if (!Version.TryParse(((MelonBase)val).Info.Version, out Version result3)) { Logger.Debug(dependency.AssemblyName + " version is not a valid version."); return new MissingDependencyInfo(dependency.Name, dependency.Version, dependency.Urls, dependency.IsRequired, "Invalid version format"); } if (result3 < result2) { Logger.Debug(dependency.AssemblyName + " version is too old."); return new MissingDependencyInfo(dependency.Name, dependency.Version, dependency.Urls, dependency.IsRequired, $"Version {result3} found, but {dependency.Version} required"); } return null; } SemVersion val2 = default(SemVersion); if (!SemVersion.TryParse(dependency.Version, ref val2, false)) { Logger.Debug(dependency.AssemblyName + " version is not a valid version."); return new MissingDependencyInfo(dependency.Name, dependency.Version, dependency.Urls, dependency.IsRequired, "Invalid version format"); } if (semanticVersion < val2) { Logger.Debug(dependency.AssemblyName + " version is too old."); return new MissingDependencyInfo(dependency.Name, dependency.Version, dependency.Urls, dependency.IsRequired, $"Version {semanticVersion} found, but {dependency.Version} required"); } return null; } } public class DependencyInfo { public string Name { get; set; } public string AssemblyName { get; set; } public string Version { get; set; } public bool IsRequired { get; set; } public List<DependencyUrl> Urls { get; set; } public DependencyInfo(string name, string version, string? assemblyName = null, List<DependencyUrl>? urls = null, bool isRequired = true) { Name = name; AssemblyName = assemblyName ?? name; Version = version; IsRequired = isRequired; Urls = urls ?? new List<DependencyUrl>(); } public DependencyInfo() { } } public class DependencyUrl { public string SourceName { get; set; } public string Url { get; set; } public DependencyUrl(string sourceName, string url) { SourceName = sourceName; Url = url; } public DependencyUrl() { } } internal static class MissingDepsPanelCreator { private static GameObject? _canvasObject; public static void Show(DependenciesChecker instance, List<DependenciesChecker.MissingDependencyInfo> deps) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_004b: Expected O, but got Unknown //IL_0074: Unknown result type (might be due to invalid IL or missing references) //IL_008a: Unknown result type (might be due to invalid IL or missing references) //IL_00a0: 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_00cc: Unknown result type (might be due to invalid IL or missing references) //IL_00f3: Unknown result type (might be due to invalid IL or missing references) //IL_0121: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Expected O, but got Unknown //IL_0150: Unknown result type (might be due to invalid IL or missing references) //IL_0157: Expected O, but got Unknown //IL_01a8: Unknown result type (might be due to invalid IL or missing references) //IL_022a: Unknown result type (might be due to invalid IL or missing references) //IL_0231: Expected O, but got Unknown //IL_02f5: Unknown result type (might be due to invalid IL or missing references) //IL_02df: Unknown result type (might be due to invalid IL or missing references) //IL_032c: Unknown result type (might be due to invalid IL or missing references) //IL_0333: Expected O, but got Unknown //IL_03a3: Unknown result type (might be due to invalid IL or missing references) Hide(); _canvasObject = new GameObject("MissingDependenciesCanvas"); Canvas val = _canvasObject.AddComponent<Canvas>(); val.renderMode = (RenderMode)0; val.sortingOrder = 9999; _canvasObject.AddComponent<GraphicRaycaster>(); GameObject val2 = new GameObject("MissingDependenciesPanel"); val2.transform.SetParent(_canvasObject.transform, false); RectTransform val3 = val2.AddComponent<RectTransform>(); val3.anchorMin = new Vector2(1f, 0.5f); val3.anchorMax = new Vector2(1f, 0.5f); val3.pivot = new Vector2(1f, 0.5f); val3.anchoredPosition = new Vector2(-20f, 0f); val3.sizeDelta = new Vector2(420f, 0f); Image val4 = val2.AddComponent<Image>(); ((Graphic)val4).color = new Color(0.08f, 0.08f, 0.08f, 0.95f); ContentSizeFitter val5 = val2.AddComponent<ContentSizeFitter>(); val5.verticalFit = (FitMode)2; VerticalLayoutGroup val6 = val2.AddComponent<VerticalLayoutGroup>(); ((LayoutGroup)val6).padding = new RectOffset(16, 16, 12, 12); ((HorizontalOrVerticalLayoutGroup)val6).spacing = 6f; ((LayoutGroup)val6).childAlignment = (TextAnchor)0; ((HorizontalOrVerticalLayoutGroup)val6).childForceExpandWidth = true; GameObject val7 = new GameObject("Header"); val7.transform.SetParent(val2.transform, false); Text val8 = val7.AddComponent<Text>(); val8.text = "Missing Dependencies"; val8.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); val8.fontSize = 18; val8.fontStyle = (FontStyle)1; ((Graphic)val8).color = Color.white; val8.alignment = (TextAnchor)3; if (deps.All((DependenciesChecker.MissingDependencyInfo d) => !d.IsRequired) && !instance.ShowBannerIfOptionalOnly) { Hide(); return; } foreach (DependenciesChecker.MissingDependencyInfo dep in deps) { GameObject val9 = new GameObject("Dep_" + dep.Name); val9.transform.SetParent(val2.transform, false); val9.AddComponent<LayoutElement>().minHeight = 20f; Text val10 = val9.AddComponent<Text>(); val10.text = " " + dep.Name + " (min v" + dep.Version + ") - " + dep.Reason; val10.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); val10.fontSize = 15; ((Graphic)val10).color = (dep.IsRequired ? new Color(1f, 0.4f, 0.4f) : new Color(1f, 0.8f, 0.3f)); val10.alignment = (TextAnchor)0; } GameObject val11 = new GameObject("Footer"); val11.transform.SetParent(val2.transform, false); Text val12 = val11.AddComponent<Text>(); val12.text = "See the console (or log at " + Path.Combine(MelonEnvironment.MelonLoaderLogsDirectory, "Latest.log") + ") for details."; val12.font = Resources.GetBuiltinResource<Font>("Arial.ttf"); val12.fontSize = 14; ((Graphic)val12).color = new Color(0.6f, 0.6f, 0.6f); val12.alignment = (TextAnchor)0; } public static void Hide() { if ((Object)(object)_canvasObject != (Object)null) { Object.Destroy((Object)(object)_canvasObject); _canvasObject = null; } } } public class Logger { private static bool _initialized; private static MethodInfo? _passLogMsgNew; private static MethodInfo? _passLogMsgLegacy; private static MethodInfo? _runMsgCallbacks; private static MethodInfo? _warningMethod; private static MethodInfo? _runWarningCallbacks; private static MethodInfo? _passLogError; private static MethodInfo? _runErrorCallbacks; private static object? _defaultTextColor; private static Func<object>? _getNsColor; public string? Namesection { get; set; } public bool RaiseTrace { get; set; } public bool RaiseDebug { get; set; } public Logger(string? namesection = null) { Namesection = namesection; } public Logger(Instance melonLogger) { FieldInfo field = typeof(Instance).GetField("Name", BindingFlags.Instance | BindingFlags.NonPublic); if (field != null) { Namesection = field.GetValue(melonLogger) as string; } } public void Trace(params object[] args) { Log(LogLevel.Trace, null, args); } public void Debug(params object[] args) { Log(LogLevel.Debug, null, args); } public void T(params object[] args) { Log(LogLevel.Trace, null, args); } public void D(params object[] args) { Log(LogLevel.Debug, null, args); } public void Info(params object[] args) { Log(LogLevel.Info, null, args); } public void Msg(params object[] args) { Log(LogLevel.Info, null, args); } public void I(params object[] args) { Log(LogLevel.Info, null, args); } public void M(params object[] args) { Log(LogLevel.Info, null, args); } public void Warning(params object[] args) { Log(LogLevel.Warning, null, args); } public void Warn(params object[] args) { Log(LogLevel.Warning, null, args); } public void W(params object[] args) { Log(LogLevel.Warning, null, args); } public void Error(params object[] args) { Log(LogLevel.Error, null, args); } public void Err(params object[] args) { Log(LogLevel.Error, null, args); } public void E(params object[] args) { Log(LogLevel.Error, null, args); } public void Fatal(params object[] args) { Log(LogLevel.BigError, null, args); } public void BigError(params object[] args) { Log(LogLevel.BigError, null, args); } public void F(params object[] args) { Log(LogLevel.BigError, null, args); } public void BE(params object[] args) { Log(LogLevel.BigError, null, args); } public void InfoColored(object txtColor, params object[] args) { Log(LogLevel.Info, txtColor, args); } public void MsgColored(object txtColor, params object[] args) { Log(LogLevel.Info, txtColor, args); } public void IC(object txtColor, params object[] args) { Log(LogLevel.Info, txtColor, args); } public void MC(object txtColor, params object[] args) { Log(LogLevel.Info, txtColor, args); } private static void EnsureInitialized() { if (_initialized) { return; } Type typeFromHandle = typeof(MelonLogger); FieldInfo field = typeFromHandle.GetField("DefaultTextColor", BindingFlags.Static | BindingFlags.Public); if (field == null) { return; } Type fieldType = field.FieldType; _defaultTextColor = field.GetValue(null); BindingFlags bindingAttr = BindingFlags.Static | BindingFlags.NonPublic; _passLogMsgNew = typeFromHandle.GetMethod("PassLogMsg", bindingAttr, null, new Type[5] { fieldType, typeof(string), fieldType, typeof(string), typeof(string) }, null); if (_passLogMsgNew == null) { _passLogMsgLegacy = typeFromHandle.GetMethod("PastelMsg", bindingAttr, null, new Type[4] { fieldType, fieldType, typeof(string), typeof(string) }, null); } _runMsgCallbacks = typeFromHandle.GetMethod("RunMsgCallbacks", bindingAttr, null, new Type[4] { fieldType, fieldType, typeof(string), typeof(string) }, null); _passLogError = typeFromHandle.GetMethod("PassLogError", bindingAttr, null, new Type[3] { typeof(string), typeof(string), typeof(bool) }, null); _runErrorCallbacks = typeFromHandle.GetMethod("RunErrorCallbacks", bindingAttr, null, new Type[2] { typeof(string), typeof(string) }, null); _runWarningCallbacks = typeFromHandle.GetMethod("RunWarningCallbacks", bindingAttr, null, new Type[2] { typeof(string), typeof(string) }, null); BindingFlags bindingAttr2 = BindingFlags.Static | BindingFlags.Public; _warningMethod = typeFromHandle.GetMethod("Warning", bindingAttr2, null, new Type[2] { typeof(string), typeof(string) }, null) ?? typeFromHandle.GetMethod("Warning", bindingAttr, null, new Type[2] { typeof(string), typeof(string) }, null); Type type = typeof(Melon<>).MakeGenericType(typeof(HeavenlyPseudo)); PropertyInfo instanceProp = type.GetProperty("Instance", BindingFlags.Static | BindingFlags.Public); if (instanceProp != null) { PropertyInfo consoleColorProp = instanceProp.PropertyType.GetProperty("ConsoleColor", BindingFlags.Instance | BindingFlags.Public); if (consoleColorProp != null) { _getNsColor = () => consoleColorProp.GetValue(instanceProp.GetValue(null)); } } if (_getNsColor == null) { _getNsColor = () => _defaultTextColor; } _initialized = true; } private static void PassLogMsg(object txtColor, string message, object nsColor, string ns) { if (_passLogMsgNew != null) { _passLogMsgNew.Invoke(null, new object[5] { txtColor, message, nsColor, ns, null }); } else if (_passLogMsgLegacy != null) { _passLogMsgLegacy.Invoke(null, new object[4] { nsColor, txtColor, ns, message }); } } private static string GetCallerInfo() { StackTrace stackTrace = new StackTrace(); for (int i = 2; i < stackTrace.FrameCount; i++) { StackFrame frame = stackTrace.GetFrame(i); MethodBase method = frame.GetMethod(); if (method?.DeclaringType != null) { return method.DeclaringType.FullName + "." + method.Name; } } return "unknown"; } private void Log(LogLevel level, object? txtColor, params object[] args) { if (args.Length == 0) { return; } string text; if (args.Length == 1) { text = args[0]?.ToString() ?? ""; } else { string format = args[0]?.ToString() ?? ""; text = string.Format(format, args.Skip(1).ToArray()); } string text2 = (string.IsNullOrWhiteSpace(Namesection) ? "HeavenlyPseudo" : ("HeavenlyPseudo." + Namesection)); EnsureInitialized(); object obj = _getNsColor(); object obj2 = txtColor ?? _defaultTextColor; switch (level) { case LogLevel.Trace: { string text3 = "[TRACE " + GetCallerInfo() + "] " + text; if (RaiseTrace) { PassLogMsg(obj2, text3, obj, text2); _runMsgCallbacks?.Invoke(null, new object[4] { obj, obj2, text3, text2 }); } else { MelonDebug.Msg(text3); } break; } case LogLevel.Debug: { string text4 = "[DEBUG " + GetCallerInfo() + "] " + text; if (RaiseDebug) { PassLogMsg(obj2, text4, obj, text2); _runMsgCallbacks?.Invoke(null, new object[4] { obj, obj2, text4, text2 }); } else { MelonDebug.Msg(text4); } break; } case LogLevel.Info: PassLogMsg(obj2, text, obj, text2); _runMsgCallbacks?.Invoke(null, new object[4] { obj, obj2, text2, text }); break; case LogLevel.Warning: _warningMethod?.Invoke(null, new object[2] { text2, text }); _runWarningCallbacks?.Invoke(null, new object[2] { text2, text }); break; case LogLevel.Error: _passLogError?.Invoke(null, new object[3] { text, text2, false }); _runErrorCallbacks?.Invoke(null, new object[2] { text2, text }); break; case LogLevel.BigError: MelonLogger.BigError(text2, text); break; } } } public enum LogLevel { Trace, Debug, Info, Warning, Error, BigError } public static class BuildInfo { public const string Name = "HeavenlyPseudo"; public const string Description = "Adds Heavenly-Quality Pseudo"; public const string Author = "k073l"; public const string Version = "1.0.0"; } public class HeavenlyPseudo : MelonMod { private static Logger Logger; public override void OnInitializeMelon() { Logger = new Logger(); Logger.Msg("HeavenlyPseudo initialized"); CheckDependencies(); } public override void OnSceneWasLoaded(int buildIndex, string sceneName) { try { PseudoCreator pseudoCreator = new PseudoCreator(); pseudoCreator.CreateItem(sceneName); } catch (Exception ex) { Logger.E("Error while creating item: " + ex.Message); } } private static void CheckDependencies() { DependenciesChecker dependenciesChecker = new DependenciesChecker { ShowMenuBanner = true, UnloadIfMissingRequired = true }; dependenciesChecker.AddDependency(new DependencyInfo { Name = "S1API (Forked)", AssemblyName = "S1API", IsRequired = true, Version = "3.0.5", Urls = new List<DependencyUrl>(3) { new DependencyUrl { SourceName = "Thunderstore", Url = "https://thunderstore.io/c/schedule-i/p/ifBars/S1API_Forked/" }, new DependencyUrl { SourceName = "NexusMods", Url = "https://www.nexusmods.com/schedule1/mods/1194" }, new DependencyUrl { SourceName = "Github", Url = "https://github.com/ifBars/S1API/releases/" } } }); dependenciesChecker.ProcessAndAlert(); } } } namespace HeavenlyPseudo.Helpers { internal class PseudoCreator { private const string HighQualityPseudoID = "highqualitypseudo"; private const string FluMedicineID = "flumedicine"; private const string HeavenlyQualityPseudoID = "heavenlyqualitypseudo"; private const string TargetRecipeID = "1xliquidmeth"; private bool _itemsInitialized = false; private static readonly Logger Log = new Logger("PseudoCreator"); internal void CreateItem(string sceneName) { if (sceneName == "Main" && !_itemsInitialized) { InitializeItems(); _itemsInitialized = true; } } private void InitializeItems() { //IL_0051: Unknown result type (might be due to invalid IL or missing references) Log.M("Creating heavenlyqualitypseudo item"); QualityItemDefinitionBuilder val = ((StorableItemDefinitionBuilderBase<QualityItemDefinitionBuilder>)(object)((StorableItemDefinitionBuilderBase<QualityItemDefinitionBuilder>)(object)((StorableItemDefinitionBuilderBase<QualityItemDefinitionBuilder>)(object)QualityItemCreator.CloneFrom("highqualitypseudo").WithDefaultQuality((Quality)4)).WithBasicInfo("heavenlyqualitypseudo", "Heavenly-Quality Pseudo", "Very high-quality pseudoephedrine in tablet form. A common precursor for meth.", (ItemCategory)9)).WithPricing(150f, 0.5f)).WithRequiredRank((FullRank?)new FullRank((Rank)5, 3)); val.Build(); MelonCoroutines.Start(Utils.WaitForPlayer(AddToChemRecipe())); } private void AddChemRecipe() { Log.M("Creating Chemistry Recipe for heavenlyqualitypseudo"); ChemistryStationRecipes.CreateAndRegister((Action<ChemistryStationRecipeBuilder>)delegate(ChemistryStationRecipeBuilder b) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) b.WithIngredient("highqualitypseudo", 1).WithIngredient("flumedicine", 1).WithProduct("heavenlyqualitypseudo", 1) .WithCalculationMethod((QualityCalculationMethod)1) .WithCookTimeMinutes(120) .WithTemperature(150f, 50f) .WithFinalLiquidColor(new Color(1f, 0.84f, 0f)) .WithTitle("Heavenly-Quality Pseudo"); }); } private IEnumerator AddToChemRecipe() { AddChemRecipe(); Log.M("Adding heavenlyqualitypseudo as valid ingredient for 1xliquidmeth"); ItemDefinition heavenlyPseudo = Registry.GetItem("heavenlyqualitypseudo"); Log.T("Adding to chem recipes"); yield return (object)new WaitUntil((Func<bool>)(() => Singleton<ChemistryStationCanvas>.InstanceExists)); StationRecipe lqMethRecipe = Singleton<ChemistryStationCanvas>.Instance.Recipes.AsEnumerable().FirstOrDefault((Func<StationRecipe, bool>)((StationRecipe r) => r.RecipeID == "1xliquidmeth")); Log.T("Recipe found, looking for the pseudo ingredient"); IngredientQuantity pseudoIngredient = lqMethRecipe?.Ingredients.AsEnumerable().FirstOrDefault((Func<IngredientQuantity, bool>)((IngredientQuantity i) => ((BaseItemDefinition)i.Item).ID == "pseudo")); Log.T("Ingredient found, adding heavenly pseudo to it"); if (!Utils.Is<QualityItemDefinition>(heavenlyPseudo, out QualityItemDefinition heavenlyPseudoAsQuality)) { Log.E("Heavenly pseudo is not a quality item definition, cannot add to recipe ingredient!"); } else { pseudoIngredient?.Items.Add((ItemDefinition)(object)heavenlyPseudoAsQuality); } } } public static class Il2CppListExtensions { public static IEnumerable<T> AsEnumerable<T>(this List<T> list) { return list ?? new List<T>(); } public static object ToNativeList<T>(this List<T> source) { return source ?? new List<T>(); } } public static class Utils { private static readonly Instance Logger = new Instance("HeavenlyPseudo-Utils"); public static T? FindObjectByName<T>(string objectName) where T : Object { try { T[] array = Resources.FindObjectsOfTypeAll<T>(); foreach (T val in array) { if (!(((Object)val).name != objectName)) { return val; } } return default(T); } catch (Exception ex) { Logger.Error("Error finding " + typeof(T).Name + " '" + objectName + "': " + ex.Message); return default(T); } } public static List<T> GetAllComponentsInChildrenRecursive<T>(GameObject obj) where T : Component { List<T> list = new List<T>(); if ((Object)(object)obj == (Object)null) { return list; } T[] components = obj.GetComponents<T>(); if (components.Length != 0) { list.AddRange(components); } for (int i = 0; i < obj.transform.childCount; i++) { Transform child = obj.transform.GetChild(i); list.AddRange(GetAllComponentsInChildrenRecursive<T>(((Component)child).gameObject)); } return list; } public static bool Is<T>(object obj, out T? result) where T : class { if (obj is T val) { result = val; return true; } result = null; return false; } public static IEnumerator WaitForPlayer(IEnumerator routine) { while ((Object)(object)Player.Local == (Object)null || (Object)(object)((Component)Player.Local).gameObject == (Object)null) { yield return null; } MelonCoroutines.Start(routine); } public static IEnumerator WaitForNetwork(IEnumerator routine) { while (!InstanceFinder.IsServer && !InstanceFinder.IsClient) { yield return null; } MelonCoroutines.Start(routine); } public static IEnumerator WaitForCondition(Func<bool> condition, float timeout = float.NaN, Action? onTimeout = null, Action? onFinish = null) { float startTime = Time.time; while (!condition()) { if (!float.IsNaN(timeout) && Time.time - startTime > timeout) { onTimeout?.Invoke(); yield break; } yield return null; } onFinish?.Invoke(); } public static string GetHierarchyPath(this Transform transform) { if ((Object)(object)transform == (Object)null) { return "null"; } string text = ((Object)transform).name; Transform parent = transform.parent; while ((Object)(object)parent != (Object)null) { text = ((Object)parent).name + "/" + text; parent = parent.parent; } return text; } public static T GetOrAddComponent<T>(this GameObject gameObject) where T : Component { T component = gameObject.GetComponent<T>(); if ((Object)(object)component != (Object)null) { return component; } return gameObject.AddComponent<T>(); } public static Material? DrawDebugVisuals(this GameObject gameObject, Color? color = null) { //IL_0040: Unknown result type (might be due to invalid IL or missing references) //IL_0045: Unknown result type (might be due to invalid IL or missing references) //IL_006d: Unknown result type (might be due to invalid IL or missing references) //IL_0097: Unknown result type (might be due to invalid IL or missing references) //IL_009d: Expected O, but got Unknown //IL_00c1: Unknown result type (might be due to invalid IL or missing references) //IL_00c6: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Unknown result type (might be due to invalid IL or missing references) //IL_0100: Unknown result type (might be due to invalid IL or missing references) //IL_012b: Unknown result type (might be due to invalid IL or missing references) //IL_0131: Unknown result type (might be due to invalid IL or missing references) //IL_0137: Unknown result type (might be due to invalid IL or missing references) //IL_013d: Unknown result type (might be due to invalid IL or missing references) //IL_0147: Unknown result type (might be due to invalid IL or missing references) Renderer component = gameObject.GetComponent<Renderer>(); if ((Object)(object)component == (Object)null) { Logger.Error("GameObject " + ((Object)gameObject).name + " has no Renderer component"); return null; } Color valueOrDefault = color.GetValueOrDefault(); if (!color.HasValue) { ((Color)(ref valueOrDefault))..ctor(1f, 0f, 1f, 0.5f); color = valueOrDefault; } Shader val = Shader.Find("Universal Render Pipeline/Lit"); if ((Object)(object)val == (Object)null) { return null; } Material val2 = new Material(val); if (val2.HasProperty("_Surface")) { val2.SetFloat("_Surface", 1f); } Color value = color.Value; if (value.a <= 0f) { value.a = 0.2f; } if (val2.HasProperty("_BaseColor")) { val2.SetColor("_BaseColor", value); } if (val2.HasProperty("_EmissionColor")) { val2.EnableKeyword("_EMISSION"); val2.SetColor("_EmissionColor", new Color(value.r, value.g, value.b) * 1.5f); } val2.SetInt("_ZWrite", 0); val2.renderQueue = 3000; Material material = component.material; component.material = val2; return material; } } } namespace System.Runtime.CompilerServices { [AttributeUsage(AttributeTargets.Assembly, AllowMultiple = true)] internal sealed class IgnoresAccessChecksToAttribute : Attribute { internal IgnoresAccessChecksToAttribute(string assemblyName) { } } }