Please disclose if any significant portion of your mod was created using AI tools by adding the 'AI Generated' category. Failing to do so may result in the mod being removed from Thunderstore.
Decompiled source of PreloadManager v1.0.1
BepInEx/patchers/PreloadManager.dll
Decompiled 2 years agousing System; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Runtime.Versioning; using System.Text.RegularExpressions; using BepInEx.Configuration; using BepInEx.Logging; using HarmonyLib; using Mono.Cecil; using Newtonsoft.Json; [assembly: CompilationRelaxations(8)] [assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)] [assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)] [assembly: AssemblyTitle("PreloadManager")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("PreloadManager")] [assembly: AssemblyCopyright("Copyright © 2024")] [assembly: AssemblyTrademark("")] [assembly: ComVisible(false)] [assembly: Guid("92838ac6-755a-4434-8fa6-d7c941a4e5f7")] [assembly: TargetFramework(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")] [assembly: AssemblyVersion("1.0.1.0")] namespace BepInEx.PreloadManager; public static class Patcher { public static ManualLogSource Logger = Logger.CreateLogSource(Id); private static readonly ConfigFile Config = new ConfigFile(Path.Combine(Paths.ConfigPath, Prefix + "." + Id + ".cfg"), true); public static ConfigEntry<bool> DisablePreloader; public static ConfigEntry<bool> DisableJsonSearch; public static ConfigEntry<string> ModList; public static string Prefix => "PXC"; public static string Id => "PreloadManager"; public static string JsonPattern => Id + ".json"; public static List<string> PluginToNeuter { get; set; } public static IEnumerable<string> TargetDLLs { get; } = new string[0]; public static void Initialize() { DateTime now = DateTime.Now; string text = "Preloader"; DisablePreloader = Config.Bind<bool>(text, "Disable Preloader", false, "This will disable this preloader entirely"); DisableJsonSearch = Config.Bind<bool>(text, "Disable Json Search", false, "Disable searching for any '" + JsonPattern + "' files in the config and plugin directories"); ModList = Config.Bind<string>(text, "Mod List", "", "This is the list of mods to patch separated by semi-colons (;) and/or a path to a json file\n\nInternal path variables:\n%ConfigPath% = Config directory\n%PluginPath% = Plugin directory"); if (DisablePreloader.Value) { Logger.LogMessage((object)"Preloader was disabled in the config - Skipping initialization!"); return; } List<string> RawItemList = new List<string>(); RawItemList = Utilities.ConvertFlatToList(ModList.Value); if (!DisableJsonSearch.Value) { List<string> searchPattern = new List<string> { "*" + JsonPattern + "*" }; Utilities.InternalVars.Values.ToList().ForEach(delegate(string path) { List<FileInfo> list2 = Utilities.FindFilesParallel(searchPattern, path).ToList(); if (list2 != null || list2.Count >= 1) { list2.ForEach(delegate(FileInfo file) { if (RawItemList == null) { RawItemList = new List<string>(); } RawItemList.Add(file.FullName); }); } }); } List<string> list = Utilities.ResolvePluginList(RawItemList); if (list != null) { PluginToNeuter = list.Distinct().ToList(); } if (PluginToNeuter == null || PluginToNeuter.Count < 1) { Logger.LogMessage((object)"Preloader has zero mods configured to modify - Skipping initialization!"); return; } Logger.LogMessage((object)$"Initializing preloader event hooks to modify {PluginToNeuter.Count} plugins..."); PluginToNeuter.ForEach(delegate(string plugin) { Logger.LogMessage((object)("Plugin to neuter: " + plugin)); }); AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad; TimeSpan value = DateTime.Now - now; Logger.LogMessage((object)("Finished initialization in: " + Utilities.ToFriendlyTime(value))); } private static void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs e) { //IL_000c: Unknown result type (might be due to invalid IL or missing references) //IL_0016: Expected O, but got Unknown //IL_007e: Unknown result type (might be due to invalid IL or missing references) //IL_0088: Expected O, but got Unknown Harmony harmony = new Harmony(Id); List<PluginData> pluginInfo = Utilities.GetPluginInfo(e.LoadedAssembly); if (pluginInfo == null || pluginInfo.Count < 1) { return; } List<PluginData> list = pluginInfo.Where((PluginData b) => PluginToNeuter.Any((string p) => Regex.IsMatch(p, "^" + Regex.Escape(b.name.Trim()) + "$", RegexOptions.IgnoreCase))).ToList(); if (list == null || list.Count < 1) { return; } HarmonyMethod harmonyMethod = new HarmonyMethod(typeof(Patcher).GetMethod("Neuter", BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy)); list.ForEach(delegate(PluginData plugin) { plugin.methods.ForEach(delegate(MethodInfo method) { string text = $"{plugin.name} v{plugin.version}"; Logger.LogMessage((object)("Attempting to remove '" + method.Name + "' from: " + text)); try { harmony.Patch((MethodBase)method, harmonyMethod, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null, (HarmonyMethod)null); Logger.LogMessage((object)("Successfully neutered: " + text)); } catch (Exception ex) { Logger.LogError((object)("Failed to neuter: " + text + " - PLEASE REPORT THIS ON GITHUB!")); Logger.LogError((object)("Exception: " + ex.Message)); } }); }); } private static bool Neuter() { return false; } public static void Patch(AssemblyDefinition _) { } } public class PluginData { public string name; public Version version; public Type type; public List<MethodInfo> methods; } public static class Utilities { public static Dictionary<string, string> InternalVars = new Dictionary<string, string> { { "%ConfigPath%", Paths.ConfigPath }, { "%PluginPath%", Paths.PluginPath } }; public static List<string> ConvertFlatToList(string list, char delimiter = ';') { if (string.IsNullOrEmpty(list)) { return null; } list = Regex.Replace(list, "\\\"", ""); return list.Split(new char[1] { delimiter }).ToList(); } public static List<string> ResolvePluginList(List<string> list) { if (list == null || list.Count < 1) { return null; } List<string> retList = new List<string>(); list.ForEach(delegate(string item) { if (Regex.IsMatch(item, "\\.json", RegexOptions.IgnoreCase)) { string text = ExpandVariables(item, InternalVars); if (File.Exists(text)) { Patcher.Logger.LogMessage((object)("Found json to load: " + text)); List<string> collection = JsonConvert.DeserializeObject<List<string>>(File.ReadAllText(text)); retList.AddRange(collection); } else { Patcher.Logger.LogWarning((object)("Unable to find [ " + text + " ] to load plugin names - Skipping...")); } } else { retList.Add(item); } }); return retList; } public static List<PluginData> GetPluginInfo(Assembly assembly) { List<PluginData> retList = null; (from t in assembly.GetTypes() where ((MemberInfo)t).GetCustomAttribute<BepInPlugin>() != null select t).ToList().ForEach(delegate(Type type) { BepInPlugin customAttribute = ((MemberInfo)type).GetCustomAttribute<BepInPlugin>(); PluginData item = new PluginData { name = customAttribute.Name, version = customAttribute.Version, type = type, methods = (from m in type.GetMethods(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.FlattenHierarchy) where m.Name == "Awake" select m).ToList() }; if (retList == null) { retList = new List<PluginData>(); } retList.Add(item); }); return retList; } public static string ExpandVariables(string Item, Dictionary<string, string> Substitutions = null) { string text = Environment.ExpandEnvironmentVariables(Item); if (Substitutions != null) { foreach (KeyValuePair<string, string> Substitution in Substitutions) { text = text.Replace(Substitution.Key, Substitution.Value); } } return text; } public static IEnumerable<FileInfo> FindFilesParallel(List<string> searchPatterns, string path, string excludePattern = null) { return searchPatterns.AsParallel().SelectMany((string searchPattern) => GetManyFileInfo(path, searchPattern, excludePattern)); } public static IEnumerable<FileInfo> GetManyFileInfo(string root, string searchPattern, string excludePattern = null) { Stack<string> pending = new Stack<string>(); pending.Push(root); while (pending.Count != 0) { string path = pending.Pop(); string[] array = null; try { array = Directory.GetFiles(path, searchPattern, SearchOption.AllDirectories); } catch { } if (array != null && array.Length != 0) { string[] array2 = array; foreach (string fileName in array2) { yield return new FileInfo(fileName); } } try { array = (string.IsNullOrEmpty(excludePattern) ? (from d in Directory.GetDirectories(path) where !Regex.IsMatch(d, excludePattern) select d).ToArray() : Directory.GetDirectories(path)); string[] array3 = array; foreach (string item in array3) { pending.Push(item); } } catch { } } } public static string ToFriendlyTime(TimeSpan? InputObject, string FormatPattern = "{0:0.00}") { try { if (!InputObject.HasValue) { return null; } if (InputObject.Value.TotalSeconds < 60.0) { return string.Format(FormatPattern + " Second(s)", InputObject.Value.TotalSeconds); } if (InputObject.Value.TotalMinutes < 60.0) { return string.Format(FormatPattern + " Minute(s)", InputObject.Value.TotalMinutes); } if (InputObject.Value.TotalHours < 24.0) { return string.Format(FormatPattern + " Hour(s)", InputObject.Value.TotalHours); } return string.Format(FormatPattern + " Day(s)", InputObject.Value.TotalDays); } catch { return null; } } }