From 788048d81c91385439d23f3e9e29283e15533deb Mon Sep 17 00:00:00 2001 From: Arimodu Date: Tue, 19 Sep 2023 09:04:44 +0200 Subject: [PATCH 1/2] Implement subfolder plugin loading --- IPA.Loader/Loader/PluginLoader.cs | 47 ++++++++++++++++++++++++++----- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/IPA.Loader/Loader/PluginLoader.cs b/IPA.Loader/Loader/PluginLoader.cs index f5252eee..4c976d50 100644 --- a/IPA.Loader/Loader/PluginLoader.cs +++ b/IPA.Loader/Loader/PluginLoader.cs @@ -83,9 +83,37 @@ namespace IPA.Loader private static readonly Regex embeddedTextDescriptionPattern = new(@"#!\[(.+)\]", RegexOptions.Compiled | RegexOptions.Singleline); + public static string[] LoadFilesRecursively(string folderPath, string fileName) + { + var dlls = new List(); + + dlls.AddRange(Directory.GetFiles(folderPath, fileName)); + + foreach (var subfolder in Directory.GetDirectories(folderPath)) + { + dlls.AddRange(LoadFilesRecursively(subfolder, fileName)); + } + + return dlls.ToArray(); + } + + public static string[] LoadDirectoriesRecursively(string folderPath) + { + var directories = new List(); + + foreach (var subfolder in Directory.GetDirectories(folderPath)) + { + directories.AddRange(LoadDirectoriesRecursively(subfolder)); + } + + directories.Add(folderPath); + + return directories.ToArray(); + } + internal static void LoadMetadata() { - string[] plugins = Directory.GetFiles(UnityGame.PluginsPath, "*.dll"); + string[] plugins = LoadFilesRecursively(UnityGame.PluginsPath, "*.dll"); try { @@ -116,13 +144,18 @@ namespace IPA.Loader } using var resolver = new CecilLibLoader(); - resolver.AddSearchDirectory(UnityGame.LibraryPath); - resolver.AddSearchDirectory(UnityGame.PluginsPath); + + foreach (var libSubDirectory in LoadDirectoriesRecursively(UnityGame.LibraryPath)) + resolver.AddSearchDirectory(libSubDirectory); + + foreach (var pluginSubDirectory in LoadDirectoriesRecursively(UnityGame.PluginsPath)) + resolver.AddSearchDirectory(pluginSubDirectory); + foreach (var plugin in plugins) { var metadata = new PluginMetadata { - File = new FileInfo(Path.Combine(UnityGame.PluginsPath, plugin)), + File = new FileInfo(plugin), IsSelf = false }; @@ -263,15 +296,15 @@ namespace IPA.Loader } } - IEnumerable bareManifests = Directory.GetFiles(UnityGame.PluginsPath, "*.json"); - bareManifests = bareManifests.Concat(Directory.GetFiles(UnityGame.PluginsPath, "*.manifest")); + IEnumerable bareManifests = LoadFilesRecursively(UnityGame.PluginsPath, "*.json"); + bareManifests = bareManifests.Concat(LoadFilesRecursively(UnityGame.PluginsPath, "*.manifest")); foreach (var manifest in bareManifests) { try { var metadata = new PluginMetadata { - File = new FileInfo(Path.Combine(UnityGame.PluginsPath, manifest)), + File = new FileInfo(manifest), IsSelf = false, IsBare = true, }; From 631032019bb6d3934dc530bbfd0b78d6c78cea33 Mon Sep 17 00:00:00 2001 From: Arimodu Date: Thu, 28 Sep 2023 11:34:56 +0200 Subject: [PATCH 2/2] Clean up and add paths to logging --- IPA.Loader/Loader/PluginLoader.cs | 74 ++++++++++++------------------- 1 file changed, 29 insertions(+), 45 deletions(-) diff --git a/IPA.Loader/Loader/PluginLoader.cs b/IPA.Loader/Loader/PluginLoader.cs index 4c976d50..11da1688 100644 --- a/IPA.Loader/Loader/PluginLoader.cs +++ b/IPA.Loader/Loader/PluginLoader.cs @@ -83,37 +83,9 @@ namespace IPA.Loader private static readonly Regex embeddedTextDescriptionPattern = new(@"#!\[(.+)\]", RegexOptions.Compiled | RegexOptions.Singleline); - public static string[] LoadFilesRecursively(string folderPath, string fileName) - { - var dlls = new List(); - - dlls.AddRange(Directory.GetFiles(folderPath, fileName)); - - foreach (var subfolder in Directory.GetDirectories(folderPath)) - { - dlls.AddRange(LoadFilesRecursively(subfolder, fileName)); - } - - return dlls.ToArray(); - } - - public static string[] LoadDirectoriesRecursively(string folderPath) - { - var directories = new List(); - - foreach (var subfolder in Directory.GetDirectories(folderPath)) - { - directories.AddRange(LoadDirectoriesRecursively(subfolder)); - } - - directories.Add(folderPath); - - return directories.ToArray(); - } - internal static void LoadMetadata() { - string[] plugins = LoadFilesRecursively(UnityGame.PluginsPath, "*.dll"); + string[] plugins = Directory.GetFiles(UnityGame.PluginsPath, "*.dll", SearchOption.AllDirectories); try { @@ -132,7 +104,7 @@ namespace IPA.Loader throw new InvalidOperationException())) manifest = manifestReader.ReadToEnd(); - selfMeta.Manifest = JsonConvert.DeserializeObject(manifest); + selfMeta.Manifest = JsonConvert.DeserializeObject(manifest) ?? throw new NotSupportedException(); PluginsMetadata.Add(selfMeta); SelfMeta = selfMeta; @@ -145,11 +117,17 @@ namespace IPA.Loader using var resolver = new CecilLibLoader(); - foreach (var libSubDirectory in LoadDirectoriesRecursively(UnityGame.LibraryPath)) - resolver.AddSearchDirectory(libSubDirectory); + foreach (var libDirectory in Directory.GetDirectories(UnityGame.LibraryPath, "*", SearchOption.AllDirectories).Where((x) => !x.Contains("Native")).Prepend(UnityGame.LibraryPath)) + { + Logger.Loader.Debug($"Adding lib search directory: {libDirectory.Replace(UnityGame.InstallPath, "").TrimStart(Path.DirectorySeparatorChar)}"); + resolver.AddSearchDirectory(libDirectory); + } - foreach (var pluginSubDirectory in LoadDirectoriesRecursively(UnityGame.PluginsPath)) - resolver.AddSearchDirectory(pluginSubDirectory); + foreach (var pluginDirectory in Directory.GetDirectories(UnityGame.PluginsPath, "*", SearchOption.AllDirectories).Where((x) => !x.Contains(".cache")).Prepend(UnityGame.PluginsPath)) + { + Logger.Loader.Debug($"Adding plugin search directory: {pluginDirectory.Replace(UnityGame.InstallPath, "").TrimStart(Path.DirectorySeparatorChar)}"); + resolver.AddSearchDirectory(pluginDirectory); + } foreach (var plugin in plugins) { @@ -159,6 +137,8 @@ namespace IPA.Loader IsSelf = false }; + var pluginRelative = plugin.Replace(UnityGame.InstallPath, "").TrimStart(Path.DirectorySeparatorChar); + try { var scanResult = AntiMalwareEngine.Engine.ScanFile(metadata.File); @@ -202,9 +182,9 @@ namespace IPA.Loader if (pluginManifest == null) { #if DIRE_LOADER_WARNINGS - Logger.loader.Error($"Could not find manifest.json for {Path.GetFileName(plugin)}"); + Logger.loader.Error($"Could not find manifest.json for {pluginRelative}"); #else - Logger.Loader.Notice($"No manifest.json in {Path.GetFileName(plugin)}"); + Logger.Loader.Notice($"No manifest.json in {pluginRelative}"); #endif continue; } @@ -277,16 +257,16 @@ namespace IPA.Loader if (metadata.PluginType == null) { - Logger.Loader.Error($"No plugin found in the manifest {(hint != null ? $"hint path ({hint}) or " : "")}namespace ({pluginNs}) in {Path.GetFileName(plugin)}"); + Logger.Loader.Error($"No plugin found in the manifest {(hint != null ? $"hint path ({hint}) or " : "")}namespace ({pluginNs}) in {pluginRelative}"); continue; } - Logger.Loader.Debug($"Adding info for {Path.GetFileName(plugin)}"); + Logger.Loader.Debug($"Adding info for {pluginRelative}"); PluginsMetadata.Add(metadata); } catch (Exception e) { - Logger.Loader.Error($"Could not load data for plugin {Path.GetFileName(plugin)}"); + Logger.Loader.Error($"Could not load data for plugin {pluginRelative}"); Logger.Loader.Error(e); ignoredPlugins.Add(metadata, new IgnoreReason(Reason.Error) { @@ -296,8 +276,8 @@ namespace IPA.Loader } } - IEnumerable bareManifests = LoadFilesRecursively(UnityGame.PluginsPath, "*.json"); - bareManifests = bareManifests.Concat(LoadFilesRecursively(UnityGame.PluginsPath, "*.manifest")); + IEnumerable bareManifests = Directory.GetFiles(UnityGame.PluginsPath, "*.json", SearchOption.AllDirectories); + bareManifests = bareManifests.Concat(Directory.GetFiles(UnityGame.PluginsPath, "*.manifest", SearchOption.AllDirectories)); foreach (var manifest in bareManifests) { try @@ -309,13 +289,15 @@ namespace IPA.Loader IsBare = true, }; - metadata.Manifest = JsonConvert.DeserializeObject(File.ReadAllText(manifest)); + metadata.Manifest = JsonConvert.DeserializeObject(File.ReadAllText(manifest)) ?? throw new NotSupportedException(); + + var manifestRelative = manifest.Replace(UnityGame.InstallPath, "").TrimStart(Path.DirectorySeparatorChar); if (metadata.Manifest.Files.Length < 1) - Logger.Loader.Warn($"Bare manifest {Path.GetFileName(manifest)} does not declare any files. " + + Logger.Loader.Warn($"Bare manifest {manifestRelative} does not declare any files. " + $"Dependency resolution and verification cannot be completed."); - Logger.Loader.Debug($"Adding info for bare manifest {Path.GetFileName(manifest)}"); + Logger.Loader.Debug($"Adding info for bare manifest {manifestRelative}"); PluginsMetadata.Add(metadata); } catch (Exception e) @@ -555,7 +537,9 @@ namespace IPA.Loader } else { - Logger.Loader.Warn($"Found duplicates of {meta.Id}, using newest"); + Logger.Loader.Warn( + $"{meta.Name}@{meta.HVersion} ({meta.File.ToString().Replace(UnityGame.InstallPath, "").TrimStart(Path.DirectorySeparatorChar)}) --- " + + $"Used plugin: {existing.Meta.File.ToString().Replace(UnityGame.InstallPath, "").TrimStart(Path.DirectorySeparatorChar)}@{existing.Meta.HVersion}"); ignoredPlugins.Add(meta, new(Reason.Duplicate) { ReasonText = $"Duplicate entry of same ID ({meta.Id})",