Some mods target the Mono version of the game, which is available by opting into the Steam beta branch "alternate"
Decompiled source of ModEnforcementAgency v0.1.0
Plugins/ModEnforcementAgency.dll
Decompiled 2 weeks agousing System; using System.Collections; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Resources; using System.Runtime.CompilerServices; using System.Runtime.Versioning; using System.Security; using System.Security.Permissions; using HarmonyLib; using Il2CppInterop.Runtime.Injection; using Il2CppInterop.Runtime.InteropTypes.Arrays; using Il2CppScheduleOne; using Il2CppScheduleOne.DevUtilities; using Il2CppScheduleOne.ItemFramework; using Il2CppScheduleOne.UI.MainMenu; using Il2CppScheduleOne.UI.Shop; using Il2CppSystem.Collections.Generic; using Il2CppSystem.IO; using Il2CppTMPro; using MelonLoader; using MelonLoader.Preferences; using Microsoft.CodeAnalysis; using ModEnforcementAgency; using ModEnforcementAgency.MainMenu; using ModEnforcementAgency.Managers; using ModEnforcementAgency.Managers.Items; using ModEnforcementAgency.Utils; using UnityEngine; using UnityEngine.Events; 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(Core), "ModEnforcementAgency", "0.1.0", "Moddy", null)] [assembly: MelonGame("TVGS", "Schedule I")] [assembly: HarmonyDontPatchAll] [assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")] [assembly: AssemblyCompany("ModEnforcementAgency")] [assembly: AssemblyConfiguration("Debug")] [assembly: AssemblyFileVersion("1.0.0.0")] [assembly: AssemblyInformationalVersion("1.0.0+6a79a3fbc4ab207727597e48f70871538fb4bb79")] [assembly: AssemblyProduct("ModEnforcementAgency")] [assembly: AssemblyTitle("ModEnforcementAgency")] [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.Module, AllowMultiple = false, Inherited = false)] internal sealed class RefSafetyRulesAttribute : Attribute { public readonly int Version; public RefSafetyRulesAttribute(int P_0) { Version = P_0; } } } namespace ModEnforcementAgency { public class Core : MelonPlugin { public static Core Instance; public const string VERSION = "0.1.0"; private bool settingsTabAdded = false; private bool versionDisplayConfigured = false; public Instance logger; internal static ModManager ModManager => ModManager.Instance; public Il2CppAssetBundle MEAContent { get; private set; } public override void OnApplicationStarted() { ModManager.RegisterMods(MelonBase.RegisteredMelons); PrefManager.Instance.Initialize(); PrefManager.Instance.RegisterAllMods(); CustomItemManager.Initialize(); MEAContent = AssetUtils.LoadAssetBundleFromResources("meacontent", ((MelonBase)this).MelonAssembly.Assembly); } public override void OnPreInitialization() { } public override void OnInitializeMelon() { //IL_002f: Unknown result type (might be due to invalid IL or missing references) //IL_0035: Expected O, but got Unknown Instance = this; logger = ((MelonBase)this).LoggerInstance; ((MelonBase)this).LoggerInstance.Msg("MEA v0.1.0 Initialized."); ClassInjector.RegisterTypeInIl2Cpp<VersionDisplayComponent>(); Harmony harmony = new Harmony("com.moddy.ModEnforcementAgency"); ApplyPatches(harmony); } private void ApplyPatches(Harmony harmony) { //IL_004d: Unknown result type (might be due to invalid IL or missing references) //IL_005a: Expected O, but got Unknown //IL_00ce: Unknown result type (might be due to invalid IL or missing references) //IL_00db: Expected O, but got Unknown MethodInfo method = typeof(SettingsScreen).GetMethod("Start", BindingFlags.Instance | BindingFlags.Public); MethodInfo method2 = typeof(Core).GetMethod("SettingsScreen_Start_Postfix", BindingFlags.Static | BindingFlags.NonPublic); if (method != null && method2 != null) { harmony.Patch((MethodBase)method, (HarmonyMethod)null, new HarmonyMethod(method2), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("Successfully patched SettingsScreen.Start"); } else { ((MelonBase)this).LoggerInstance.Error("Failed to patch SettingsScreen.Start"); } MethodInfo method3 = typeof(MainMenuRig).GetMethod("LoadStuff", BindingFlags.Instance | BindingFlags.Public); MethodInfo method4 = typeof(Core).GetMethod("MainMenuScreen_Open_Postfix", BindingFlags.Static | BindingFlags.NonPublic); if (method3 != null && method4 != null) { harmony.Patch((MethodBase)method3, (HarmonyMethod)null, new HarmonyMethod(method4), (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); ((MelonBase)this).LoggerInstance.Msg("Successfully patched MainMenuScreen.Open"); } else { ((MelonBase)this).LoggerInstance.Error("Failed to patch MainMenuScreen.Open"); } } [HarmonyPatch(typeof(SettingsScreen), "Start")] private static void SettingsScreen_Start_Postfix(SettingsScreen __instance) { if (Instance != null && !Instance.settingsTabAdded) { ((MelonBase)Instance).LoggerInstance.Msg("Adding mod settings tab to settings screen"); MelonCoroutines.Start(ModSettingsMenu.AddModCategory(__instance)); Instance.settingsTabAdded = true; } } [HarmonyPatch(typeof(MainMenuRig), "LoadStuff")] private static void MainMenuScreen_Open_Postfix(MainMenuScreen __instance) { if (Instance != null && !Instance.versionDisplayConfigured) { MelonCoroutines.Start(FontUtils.LoadFonts()); MelonCoroutines.Start(VersionDisplayComponent.AddVersionDisplayWithDelay()); Instance.versionDisplayConfigured = true; ((MelonBase)Instance).LoggerInstance.Msg("Version display configured successfully"); } } } } namespace ModEnforcementAgency.Utils { internal class FontUtils { public static Font italicFont; public static Font normalFont; public static Font boldFont; public static IEnumerator LoadFonts() { yield return null; Font[] fonts = Il2CppArrayBase<Font>.op_Implicit(Resources.FindObjectsOfTypeAll<Font>()); List<Font> fontList = new List<Font>(fonts); if (fontList.Count == 0) { ((MelonBase)Core.Instance).LoggerInstance.Warning("No fonts found in the scene."); } else if (fontList.Count > 0) { italicFont = fontList[0]; normalFont = ((fontList.Count > 1) ? fontList[1] : italicFont); boldFont = ((fontList.Count > 2) ? fontList[2] : italicFont); ((MelonBase)Core.Instance).LoggerInstance.Msg($"Fonts loaded: Italic: {((Object)italicFont).name}, Normal: {((Object)normalFont).name}, Bold: {((Object)boldFont).name}"); } } } public static class AssetUtils { public static Il2CppAssetBundle LoadAssetBundleFromResources(string bundleName, Assembly resourceAssembly) { //IL_00c0: Unknown result type (might be due to invalid IL or missing references) //IL_00c7: Expected O, but got Unknown if (resourceAssembly == null) { throw new ArgumentNullException("Parameter resourceAssembly can not be null."); } string text = null; try { text = resourceAssembly.GetManifestResourceNames().Single((string str) => str.EndsWith(bundleName)); } catch (Exception) { } if (text == null) { ((MelonBase)Core.Instance).LoggerInstance.Error("AssetBundle " + bundleName + " not found in assembly manifest"); return null; } Il2CppAssetBundle result; using (Stream stream = resourceAssembly.GetManifestResourceStream(text)) { if (stream == null) { ((MelonBase)Core.Instance).LoggerInstance.Error("Failed to load AssetBundle " + bundleName + " from stream."); return null; } Stream val = (Stream)new MemoryStream(); byte[] array = new byte[4096]; int num; while ((num = stream.Read(array, 0, array.Length)) > 0) { val.Write(Il2CppStructArray<byte>.op_Implicit(array), 0, num); } val.Position = 0L; result = Il2CppAssetBundleManager.LoadFromStream(val); } return result; } public static Il2CppAssetBundle LoadAssetBundleFromAbsolutePath(string absolutePath) { //IL_0064: Unknown result type (might be due to invalid IL or missing references) //IL_006b: Expected O, but got Unknown if (string.IsNullOrEmpty(absolutePath)) { ((MelonBase)Core.Instance).LoggerInstance.Error("Absolute path cannot be null or empty."); return null; } if (!File.Exists(absolutePath)) { ((MelonBase)Core.Instance).LoggerInstance.Error("AssetBundle file not found at path: " + absolutePath); return null; } try { byte[] array = File.ReadAllBytes(absolutePath); MemoryStream val = new MemoryStream(Il2CppStructArray<byte>.op_Implicit(array)); Il2CppAssetBundle val2 = Il2CppAssetBundleManager.LoadFromStream((Stream)(object)val); if (val2 == null) { ((MelonBase)Core.Instance).LoggerInstance.Error("Failed to load AssetBundle from path: " + absolutePath); return null; } return val2; } catch (Exception ex) { ((MelonBase)Core.Instance).LoggerInstance.Error("Exception loading AssetBundle from path " + absolutePath + ": " + ex.Message); return null; } } public static Il2CppAssetBundle LoadAssetBundleFromRelativePath(string relativePath, Assembly assembly) { if (assembly == null) { throw new ArgumentNullException("Parameter assembly cannot be null."); } if (string.IsNullOrEmpty(relativePath)) { ((MelonBase)Core.Instance).LoggerInstance.Error("Relative path cannot be null or empty."); return null; } try { string directoryName = Path.GetDirectoryName(assembly.Location); string absolutePath = Path.Combine(directoryName, relativePath); return LoadAssetBundleFromAbsolutePath(absolutePath); } catch (Exception ex) { ((MelonBase)Core.Instance).LoggerInstance.Error("Exception resolving relative path: " + ex.Message); return null; } } } } namespace ModEnforcementAgency.MainMenu { internal class ModSettingsMenu { public static GameObject templateMod; public static IEnumerator AddModCategory(SettingsScreen settingsScreen) { yield return null; try { if ((Object)(object)settingsScreen == (Object)null) { ((MelonBase)Core.Instance).LoggerInstance.Error("SettingsScreen is null"); yield break; } Il2CppReferenceArray<SettingsCategory> categories = settingsScreen.Categories; if (categories == null || ((Il2CppArrayBase<SettingsCategory>)(object)categories).Length == 0) { ((MelonBase)Core.Instance).LoggerInstance.Error("Categories array is null or empty"); yield break; } SettingsCategory modCategory = new SettingsCategory(); Button firstButton = ((Il2CppArrayBase<SettingsCategory>)(object)categories)[1].Button; if ((Object)(object)firstButton == (Object)null) { ((MelonBase)Core.Instance).LoggerInstance.Error("First category button is null"); yield break; } GameObject buttonParentObj = ((Component)((Component)firstButton).gameObject.transform.parent).gameObject; GameObject buttonObj = Object.Instantiate<GameObject>(((Component)firstButton).gameObject, buttonParentObj.transform); ((Object)buttonObj).name = "ModSettingsButton"; Button button = buttonObj.GetComponent<Button>(); TextMeshProUGUI buttonText = buttonObj.GetComponentInChildren<TextMeshProUGUI>(); if ((Object)(object)buttonText != (Object)null) { ((TMP_Text)buttonText).text = "Mods"; } GameObject firstPanel = ((Il2CppArrayBase<SettingsCategory>)(object)categories)[0].Panel; if ((Object)(object)firstPanel == (Object)null) { ((MelonBase)Core.Instance).LoggerInstance.Error("First category panel is null"); yield break; } GameObject panelParentObj = ((Component)firstPanel.transform.parent).gameObject; GameObject uiPrefab = Object.Instantiate<GameObject>(Core.Instance.MEAContent.LoadAsset<GameObject>("UI_InstalledMods")); uiPrefab.transform.SetParent(panelParentObj.transform, false); ((Object)uiPrefab).name = "ModSettingsPanel"; Transform contentTransform = uiPrefab.transform.Find("Scroll View/Viewport/Content"); if ((Object)(object)contentTransform == (Object)null) { ((MelonBase)Core.Instance).LoggerInstance.Error("Content transform not found in UI_InstalledMods prefab"); yield break; } templateMod = ((Component)((Component)contentTransform).transform.Find("TemplateMod")).gameObject; templateMod.SetActive(false); int modCount = 0; foreach (MelonBase mod in MelonBase.RegisteredMelons) { if (mod == null) { ((MelonBase)Core.Instance).LoggerInstance.Warning("Encountered a null mod during mod settings UI creation"); continue; } new ModInfoDisplay(mod, ((Component)contentTransform).gameObject); modCount++; } modCategory.Button = button; modCategory.Panel = uiPrefab; uiPrefab.SetActive(false); Il2CppReferenceArray<SettingsCategory> newCategories = new Il2CppReferenceArray<SettingsCategory>((long)(((Il2CppArrayBase<SettingsCategory>)(object)categories).Length + 1)); for (int i = 0; i < ((Il2CppArrayBase<SettingsCategory>)(object)categories).Length; i++) { ((Il2CppArrayBase<SettingsCategory>)(object)newCategories)[i] = ((Il2CppArrayBase<SettingsCategory>)(object)categories)[i]; } ((Il2CppArrayBase<SettingsCategory>)(object)newCategories)[((Il2CppArrayBase<SettingsCategory>)(object)categories).Length] = modCategory; settingsScreen.Categories = newCategories; int categoryIndex = ((Il2CppArrayBase<SettingsCategory>)(object)categories).Length; ((UnityEvent)button.onClick).AddListener(UnityAction.op_Implicit((Action)delegate { settingsScreen.ShowCategory(categoryIndex); })); ((MelonBase)Core.Instance).LoggerInstance.Msg("Added mod settings tab"); } catch (Exception ex) { ((MelonBase)Core.Instance).LoggerInstance.Error("Error adding mod settings tab: " + ex.Message + "\n" + ex.StackTrace); } } } internal class ModInfoDisplay { private MelonBase mod; private GameObject modInfoContainer; public float PreferredHeight { get; private set; } = 70f; public ModInfoDisplay(MelonBase mod, GameObject parent) { //IL_0063: Unknown result type (might be due to invalid IL or missing references) //IL_0069: Expected O, but got Unknown //IL_0089: Unknown result type (might be due to invalid IL or missing references) //IL_0095: Unknown result type (might be due to invalid IL or missing references) //IL_00a1: Unknown result type (might be due to invalid IL or missing references) //IL_00b7: Unknown result type (might be due to invalid IL or missing references) //IL_00cd: Unknown result type (might be due to invalid IL or missing references) //IL_00dd: Unknown result type (might be due to invalid IL or missing references) //IL_00e3: Expected O, but got Unknown //IL_0108: Unknown result type (might be due to invalid IL or missing references) //IL_011e: Unknown result type (might be due to invalid IL or missing references) //IL_0134: Unknown result type (might be due to invalid IL or missing references) //IL_014a: Unknown result type (might be due to invalid IL or missing references) //IL_0156: Unknown result type (might be due to invalid IL or missing references) //IL_01ae: Unknown result type (might be due to invalid IL or missing references) //IL_01cb: Unknown result type (might be due to invalid IL or missing references) //IL_01d2: Expected O, but got Unknown //IL_01fb: Unknown result type (might be due to invalid IL or missing references) //IL_0212: Unknown result type (might be due to invalid IL or missing references) //IL_0229: Unknown result type (might be due to invalid IL or missing references) //IL_0240: Unknown result type (might be due to invalid IL or missing references) //IL_0257: Unknown result type (might be due to invalid IL or missing references) //IL_02b1: Unknown result type (might be due to invalid IL or missing references) //IL_02d7: Unknown result type (might be due to invalid IL or missing references) //IL_02de: Expected O, but got Unknown //IL_0307: Unknown result type (might be due to invalid IL or missing references) //IL_031e: Unknown result type (might be due to invalid IL or missing references) //IL_0335: Unknown result type (might be due to invalid IL or missing references) //IL_034c: Unknown result type (might be due to invalid IL or missing references) //IL_0363: Unknown result type (might be due to invalid IL or missing references) //IL_03bd: Unknown result type (might be due to invalid IL or missing references) //IL_03e3: Unknown result type (might be due to invalid IL or missing references) //IL_03ea: Expected O, but got Unknown //IL_0413: Unknown result type (might be due to invalid IL or missing references) //IL_042a: Unknown result type (might be due to invalid IL or missing references) //IL_0441: Unknown result type (might be due to invalid IL or missing references) //IL_0458: Unknown result type (might be due to invalid IL or missing references) //IL_046f: Unknown result type (might be due to invalid IL or missing references) //IL_04d2: Unknown result type (might be due to invalid IL or missing references) this.mod = mod; modInfoContainer = Object.Instantiate<GameObject>(ModSettingsMenu.templateMod, parent.transform); modInfoContainer.SetActive(true); ((Object)modInfoContainer).name = "ModInfo_" + mod.Info.Name; GameObject val = new GameObject("ContentLayout"); val.transform.SetParent(modInfoContainer.transform, false); RectTransform val2 = val.AddComponent<RectTransform>(); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.sizeDelta = Vector2.zero; val2.offsetMin = new Vector2(10f, 10f); val2.offsetMax = new Vector2(-10f, -10f); GameObject val3 = new GameObject("ModName"); val3.transform.SetParent(val.transform, false); RectTransform val4 = val3.AddComponent<RectTransform>(); val4.anchorMin = new Vector2(0f, 1f); val4.anchorMax = new Vector2(1f, 1f); val4.pivot = new Vector2(0f, 1f); val4.sizeDelta = new Vector2(0f, 25f); val4.anchoredPosition = Vector2.zero; Text val5 = val3.AddComponent<Text>(); val5.text = mod.Info.Name; val5.fontSize = 16; val5.fontStyle = (FontStyle)1; val5.alignment = (TextAnchor)3; ((Graphic)val5).color = new Color(0.9f, 0.9f, 0.9f, 1f); val5.font = FontUtils.boldFont; GameObject val6 = new GameObject("ModVersion"); val6.transform.SetParent(val.transform, false); RectTransform val7 = val6.AddComponent<RectTransform>(); val7.anchorMin = new Vector2(0f, 1f); val7.anchorMax = new Vector2(1f, 1f); val7.pivot = new Vector2(0f, 1f); val7.sizeDelta = new Vector2(0f, 18f); val7.anchoredPosition = new Vector2(0f, -25f); Text val8 = val6.AddComponent<Text>(); val8.text = "Version: " + mod.Info.Version; val8.fontSize = 14; val8.alignment = (TextAnchor)3; ((Graphic)val8).color = new Color(0.8f, 0.8f, 0.8f, 1f); val8.font = FontUtils.normalFont; val8.resizeTextForBestFit = true; GameObject val9 = new GameObject("ModAuthor"); val9.transform.SetParent(val.transform, false); RectTransform val10 = val9.AddComponent<RectTransform>(); val10.anchorMin = new Vector2(0f, 1f); val10.anchorMax = new Vector2(1f, 1f); val10.pivot = new Vector2(0f, 1f); val10.sizeDelta = new Vector2(0f, 18f); val10.anchoredPosition = new Vector2(0f, -43f); Text val11 = val9.AddComponent<Text>(); val11.text = "Author: " + mod.Info.Author; val11.fontSize = 14; val11.alignment = (TextAnchor)3; ((Graphic)val11).color = new Color(0.8f, 0.8f, 0.8f, 1f); val11.font = FontUtils.normalFont; val11.resizeTextForBestFit = true; GameObject val12 = new GameObject("ModAssembly"); val12.transform.SetParent(val.transform, false); RectTransform val13 = val12.AddComponent<RectTransform>(); val13.anchorMin = new Vector2(0f, 1f); val13.anchorMax = new Vector2(1f, 1f); val13.pivot = new Vector2(0f, 1f); val13.sizeDelta = new Vector2(0f, 18f); val13.anchoredPosition = new Vector2(0f, -61f); Text val14 = val12.AddComponent<Text>(); string fileName = Path.GetFileName(mod.MelonAssembly.Location); val14.text = "Assembly: " + fileName; val14.fontSize = 12; val14.alignment = (TextAnchor)3; ((Graphic)val14).color = new Color(0.7f, 0.7f, 0.7f, 1f); val14.font = FontUtils.normalFont; } } [RegisterTypeInIl2Cpp] public class VersionDisplayComponent : MonoBehaviour { private static GameObject versionDisplay; private GameObject textObj; private Text versionText; public VersionDisplayComponent(IntPtr ptr) : base(ptr) { } public void SetVersion(string version) { //IL_0008: Unknown result type (might be due to invalid IL or missing references) //IL_0012: Expected O, but got Unknown //IL_0041: Unknown result type (might be due to invalid IL or missing references) //IL_0057: 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_0083: Unknown result type (might be due to invalid IL or missing references) //IL_0099: 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_00bd: Unknown result type (might be due to invalid IL or missing references) //IL_00c9: Unknown result type (might be due to invalid IL or missing references) //IL_00d5: Unknown result type (might be due to invalid IL or missing references) //IL_0101: Unknown result type (might be due to invalid IL or missing references) //IL_0148: Unknown result type (might be due to invalid IL or missing references) try { textObj = new GameObject("VersionText"); textObj.transform.SetParent(((Component)this).transform, false); RectTransform val = ((Component)this).gameObject.AddComponent<RectTransform>(); val.anchorMin = new Vector2(0f, 0f); val.anchorMax = new Vector2(0f, 0f); val.pivot = new Vector2(0f, 0f); val.anchoredPosition = new Vector2(10f, 10f); val.sizeDelta = new Vector2(200f, 30f); RectTransform val2 = textObj.AddComponent<RectTransform>(); val2.anchorMin = Vector2.zero; val2.anchorMax = Vector2.one; val2.offsetMin = Vector2.zero; val2.offsetMax = Vector2.zero; Image val3 = ((Component)this).gameObject.AddComponent<Image>(); ((Graphic)val3).color = new Color(0f, 0f, 0f, 0.5f); versionText = textObj.AddComponent<Text>(); versionText.text = "MEA v" + version; versionText.fontSize = 14; ((Graphic)versionText).color = Color.white; versionText.alignment = (TextAnchor)4; versionText.font = FontUtils.normalFont; ((MelonBase)Core.Instance).LoggerInstance.Msg("Version display configured successfully"); } catch (Exception ex) { ((MelonBase)Core.Instance).LoggerInstance.Error("Error setting up version display: " + ex.Message); } } public static IEnumerator AddVersionDisplayWithDelay() { for (int i = 0; i < 5; i++) { yield return null; } try { Canvas canvas = Object.FindObjectOfType<Canvas>(); if ((Object)(object)canvas != (Object)null && (Object)(object)versionDisplay == (Object)null) { versionDisplay = new GameObject("MEAVersionDisplay"); versionDisplay.transform.SetParent(((Component)canvas).transform, false); VersionDisplayComponent versionComponent = versionDisplay.AddComponent<VersionDisplayComponent>(); versionComponent.SetVersion("0.1.0"); ((MelonBase)Core.Instance).LoggerInstance.Msg("Added version display component"); } } catch (Exception ex) { ((MelonBase)Core.Instance).LoggerInstance.Error("Error adding version display: " + ex.Message + "\n" + ex.StackTrace); } } } } namespace ModEnforcementAgency.Managers { internal class PrefManager { private static PrefManager _instance; private MelonPreferences_Category modConfigCategory; private MelonPreferences_Category userSettingsCategory; private MelonPreferences_Entry<bool> enabledModsAutoSave; private MelonPreferences_Entry<string> lastLoadedProfile; private Dictionary<string, MelonPreferences_Entry<bool>> modEnabledStateEntries; private const string MOD_PROFILES_DIR = "UserData/ModProfiles"; private const string CURRENT_PROFILE_FILENAME = "CurrentProfile.cfg"; public static PrefManager Instance { get { if (_instance == null) { _instance = new PrefManager(); } return _instance; } } public void Initialize() { //IL_00af: Unknown result type (might be due to invalid IL or missing references) //IL_00bb: Expected O, but got Unknown if (!Directory.Exists("UserData/ModProfiles")) { Directory.CreateDirectory("UserData/ModProfiles"); } modConfigCategory = MelonPreferences.CreateCategory("MEA_ModConfiguration"); userSettingsCategory = MelonPreferences.CreateCategory("MEA_UserSettings"); modConfigCategory.SetFilePath(Path.Combine("UserData/ModProfiles", "CurrentProfile.cfg")); enabledModsAutoSave = userSettingsCategory.CreateEntry<bool>("EnabledModsAutoSave", true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); lastLoadedProfile = userSettingsCategory.CreateEntry<string>("LastLoadedProfile", "Default", (string)null, (string)null, false, false, (ValueValidator)null, (string)null); modEnabledStateEntries = new Dictionary<string, MelonPreferences_Entry<bool>>(); ((MelonEventBase<LemonAction>)(object)MelonEvents.OnApplicationQuit).Subscribe(new LemonAction(SaveAllPreferences), 0, false); } public void SaveAllPreferences() { MelonPreferences.Save(); modConfigCategory.SaveToFile(true); } public void RegisterMod(MelonBase mod) { if (mod != null) { string modIdentifier = GetModIdentifier(mod); if (!modEnabledStateEntries.ContainsKey(modIdentifier)) { MelonPreferences_Entry<bool> value = modConfigCategory.CreateEntry<bool>(modIdentifier, true, (string)null, (string)null, false, false, (ValueValidator)null, (string)null); modEnabledStateEntries.Add(modIdentifier, value); } } } public void RegisterAllMods() { List<MelonBase> loadedMods = ModManager.Instance.LoadedMods; if (loadedMods == null) { return; } foreach (MelonBase item in loadedMods) { RegisterMod(item); } } public bool IsModEnabled(MelonBase mod) { if (mod == null) { return false; } string modIdentifier = GetModIdentifier(mod); if (modEnabledStateEntries.TryGetValue(modIdentifier, out var value)) { return value.Value; } RegisterMod(mod); return true; } public void SetModEnabled(MelonBase mod, bool enabled) { if (mod != null) { string modIdentifier = GetModIdentifier(mod); if (modEnabledStateEntries.TryGetValue(modIdentifier, out var value)) { value.Value = enabled; } else { RegisterMod(mod); modEnabledStateEntries[modIdentifier].Value = enabled; } if (enabledModsAutoSave.Value) { modConfigCategory.SaveToFile(true); } } } public void CreateProfile(string profileName) { if (!string.IsNullOrWhiteSpace(profileName)) { modConfigCategory.SaveToFile(true); string text = Path.Combine("UserData/ModProfiles", profileName + ".cfg"); modConfigCategory.SetFilePath(text, false); modConfigCategory.SaveToFile(true); lastLoadedProfile.Value = profileName; userSettingsCategory.SaveToFile(true); } } public void LoadProfile(string profileName) { if (!string.IsNullOrWhiteSpace(profileName)) { string text = Path.Combine("UserData/ModProfiles", profileName + ".cfg"); if (!File.Exists(text)) { MelonLogger.Warning("Profile '" + profileName + "' does not exist. Creating new profile."); CreateProfile(profileName); return; } modConfigCategory.SetFilePath(text); RefreshModEnabledStateEntries(); lastLoadedProfile.Value = profileName; userSettingsCategory.SaveToFile(true); } } public List<string> GetAvailableProfiles() { List<string> list = new List<string>(); if (Directory.Exists("UserData/ModProfiles")) { string[] files = Directory.GetFiles("UserData/ModProfiles", "*.cfg"); foreach (string path in files) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(path); list.Add(fileNameWithoutExtension); } } return list; } private string GetModIdentifier(MelonBase mod) { return mod.Info.Name + "_" + mod.MelonAssembly.Assembly.GetName().Name; } private void RefreshModEnabledStateEntries() { modEnabledStateEntries.Clear(); foreach (MelonPreferences_Entry entry in modConfigCategory.Entries) { if (entry is MelonPreferences_Entry<bool> value) { modEnabledStateEntries.Add(entry.Identifier, value); } } RegisterAllMods(); } private PrefManager() { modEnabledStateEntries = new Dictionary<string, MelonPreferences_Entry<bool>>(); } } internal class ModManager { private static ModManager _instance; public static ModManager Instance { get { if (_instance == null) { _instance = new ModManager(); } return _instance; } } public List<MelonBase> LoadedMods { get; private set; } internal void RegisterMods(ReadOnlyCollection<MelonBase> loadedAssemblies) { if (LoadedMods == null) { LoadedMods = new List<MelonBase>(); } LoadedMods.Clear(); foreach (MelonBase loadedAssembly in loadedAssemblies) { if (loadedAssembly != null) { LoadedMods.Add(loadedAssembly); } else { ((MelonBase)Core.Instance).LoggerInstance.Warning("Encountered a null mod during registration"); } } } private ModManager() { LoadedMods = new List<MelonBase>(); } } } namespace ModEnforcementAgency.Managers.Items { public static class CustomItemManager { public enum EShopType { GasStation, HardwareStore, HardwareStoreNorth, GasStationCentral, WeedSupplier, MethSupplier, CokeSupplier, DarkMarket } private struct ShopPathMapping { public EShopType ShopType; public string Path; public ShopPathMapping(EShopType shopType, string path) { ShopType = shopType; Path = path; } } private class ShopItemMapping { public string ItemId { get; set; } public bool OverridePrice { get; set; } public float Price { get; set; } } private static readonly Dictionary<string, ItemDefinition> CustomItems = new Dictionary<string, ItemDefinition>(); private static readonly Dictionary<string, StorableItemDefinition> CustomStorableItems = new Dictionary<string, StorableItemDefinition>(); private static readonly Instance Logger = new Instance("MEA.CustomItemAPI"); private static bool registryInitialized = false; private static readonly Dictionary<EShopType, ShopInterface> CachedShops = new Dictionary<EShopType, ShopInterface>(); private static readonly ShopPathMapping[] KnownShopPaths = new ShopPathMapping[8] { new ShopPathMapping(EShopType.GasStation, "UI/GasStationInterface"), new ShopPathMapping(EShopType.HardwareStore, "UI/HardwareStoreInterface"), new ShopPathMapping(EShopType.HardwareStoreNorth, "UI/HardwareStoreInterface (North Store)"), new ShopPathMapping(EShopType.GasStationCentral, "UI/GasStationInterface_Central"), new ShopPathMapping(EShopType.WeedSupplier, "UI/Supplier Stores/WeedSupplierInterface"), new ShopPathMapping(EShopType.MethSupplier, "UI/Supplier Stores/MethSupplierInterface"), new ShopPathMapping(EShopType.CokeSupplier, "UI/Supplier Stores/CokeSupplierInterface"), new ShopPathMapping(EShopType.DarkMarket, "UI/DarkMarketInterface") }; private static Dictionary<EShopType, List<ShopItemMapping>> shopItemMappings = new Dictionary<EShopType, List<ShopItemMapping>>(); public static void Initialize() { ((MelonEventBase<LemonAction<int, string>>)(object)MelonEvents.OnSceneWasLoaded).Subscribe((LemonAction<int, string>)delegate(int buildIndex, string sceneName) { if (sceneName == "Main" && !registryInitialized) { RegisterCachedItems(); CacheShopsAndAddItems(); } }, 0, false); Logger.Msg("Custom Item API initialized"); } public static ItemDefinition RegisterItem(ItemDefinition itemDef) { StorableItemDefinition val = (StorableItemDefinition)(object)((itemDef is StorableItemDefinition) ? itemDef : null); if (val != null) { CustomStorableItems[itemDef.ID] = val; Logger.Msg("Stored " + itemDef.ID + " as StorableItemDefinition type: " + ((object)val).GetType().Name); } if (CustomItems.ContainsKey(itemDef.ID)) { Logger.Warning("Item with ID " + itemDef.ID + " already exists! Returning existing item."); return CustomItems[itemDef.ID]; } CustomItems.Add(itemDef.ID, itemDef); Logger.Msg("Custom item registered: " + itemDef.ID); if (registryInitialized && (Object)(object)Singleton<Registry>.Instance != (Object)null) { try { Singleton<Registry>.Instance.AddToRegistry(itemDef); Logger.Msg("Added " + itemDef.ID + " to game registry immediately"); } catch (Exception ex) { Logger.Error("Failed to add item " + itemDef.ID + " to registry: " + ex.Message); } } return itemDef; } public static StorableItemDefinition GetStorableItem(string itemId) { if (CustomStorableItems.TryGetValue(itemId, out var value)) { return value; } ItemDefinition item = Registry.GetItem(itemId); StorableItemDefinition val = (StorableItemDefinition)(object)((item is StorableItemDefinition) ? item : null); if (val != null) { return val; } return null; } public static void AddItemToShop(EShopType shopType, string itemId, float overridePrice = -1f) { if (!shopItemMappings.ContainsKey(shopType)) { shopItemMappings[shopType] = new List<ShopItemMapping>(); } shopItemMappings[shopType].Add(new ShopItemMapping { ItemId = itemId, OverridePrice = (overridePrice > 0f), Price = overridePrice }); Logger.Msg($"Queued item {itemId} to be added to shop {shopType}"); if (registryInitialized && CachedShops.TryGetValue(shopType, out var value)) { AddItemToShopInternal(value, itemId, overridePrice > 0f, overridePrice); if (value.IsOpen) { value.RefreshShownItems(); } } } public static Sprite LoadSpriteFromAssetBundle(string bundleName, string assetName, Assembly resourceAssembly) { try { Il2CppAssetBundle val = AssetUtils.LoadAssetBundleFromResources(bundleName, resourceAssembly); if (val == null) { return null; } return val.LoadAsset<Sprite>(assetName); } catch (Exception ex) { Logger.Error("Failed to load sprite from asset bundle: " + ex.Message); return null; } } public static void RefreshShop(EShopType shopType) { if (CachedShops.TryGetValue(shopType, out var value)) { value.RefreshShownItems(); Logger.Msg($"Refreshed shop {shopType}"); } else { Logger.Warning($"Cannot refresh shop {shopType}: Shop not found in cache"); } } private static void CacheShopsAndAddItems() { try { CachedShops.Clear(); ShopPathMapping[] knownShopPaths = KnownShopPaths; for (int i = 0; i < knownShopPaths.Length; i++) { ShopPathMapping shopPathMapping = knownShopPaths[i]; GameObject val = GameObject.Find(shopPathMapping.Path); if ((Object)(object)val != (Object)null) { ShopInterface component = val.GetComponent<ShopInterface>(); if ((Object)(object)component != (Object)null) { CachedShops[shopPathMapping.ShopType] = component; Logger.Msg($"Cached shop: {shopPathMapping.ShopType} from path {shopPathMapping.Path}"); } else { Logger.Warning("Shop GameObject found at " + shopPathMapping.Path + " but doesn't have ShopInterface component"); } } else { Logger.Warning("Shop GameObject not found at path: " + shopPathMapping.Path); } } foreach (KeyValuePair<EShopType, List<ShopItemMapping>> shopItemMapping in shopItemMappings) { EShopType key = shopItemMapping.Key; List<ShopItemMapping> value = shopItemMapping.Value; if (CachedShops.TryGetValue(key, out var value2)) { foreach (ShopItemMapping item in value) { AddItemToShopInternal(value2, item.ItemId, item.OverridePrice, item.Price); } value2.RefreshShownItems(); Logger.Msg($"Added {value.Count} items to shop: {key}"); } else { Logger.Warning($"Failed to add items to shop {key}: Shop not found in cache"); } } } catch (Exception ex) { Logger.Error("Error in CacheShopsAndAddItems: " + ex.Message + "\n" + ex.StackTrace); } } private static void AddItemToShopInternal(ShopInterface shop, string itemId, bool overridePrice, float price) { //IL_00d6: Unknown result type (might be due to invalid IL or missing references) //IL_00dc: Expected O, but got Unknown try { StorableItemDefinition storableItem = GetStorableItem(itemId); if ((Object)(object)storableItem == (Object)null) { Logger.Warning($"Cannot add item {itemId} to shop {shop.ShopName}: Item not found or not a StorableItemDefinition"); return; } Enumerator<ShopListing> enumerator = shop.Listings.GetEnumerator(); while (enumerator.MoveNext()) { ShopListing current = enumerator.Current; if (((ItemDefinition)current.Item).ID == itemId) { Logger.Msg("Item " + itemId + " already in shop " + shop.ShopName); return; } } ShopListing val = new ShopListing(); val.Item = storableItem; if (overridePrice) { val.OverridePrice = true; val.OverriddenPrice = price; } shop.Listings.Add(val); shop.CreateListingUI(val); Logger.Msg("Added item " + itemId + " to shop " + shop.ShopName); } catch (Exception ex) { Logger.Error($"Error adding {itemId} to shop {shop.ShopName}: {ex.Message}"); } } private static void RegisterCachedItems() { Registry instance = Singleton<Registry>.Instance; if ((Object)(object)instance == (Object)null) { Logger.Error("Registry instance not found! Items will not be registered."); return; } foreach (ItemDefinition value in CustomItems.Values) { try { instance.AddToRegistry(value); Logger.Msg("Added " + value.ID + " to game registry"); } catch (Exception ex) { Logger.Error("Failed to register item " + value.ID + ": " + ex.Message); } } registryInitialized = true; } } }