Skip to content

Commit

Permalink
Implemented Melon Preprocessor to prevent Loading Duplicates
Browse files Browse the repository at this point in the history
  • Loading branch information
HerpDerpinstine committed Nov 4, 2024
1 parent bbce3a6 commit 41ed941
Show file tree
Hide file tree
Showing 2 changed files with 97 additions and 39 deletions.
41 changes: 2 additions & 39 deletions MelonLoader/Melons/MelonFolderHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,41 +90,6 @@ internal static void ScanMelons<T>(string path) where T : MelonTypeBase<T>
firstSpacer = true;
}

private static void LoadFolder(string path,
bool addToList,
ref bool hasWroteLine,
ref List<MelonAssembly> melonAssemblies)
{
// Validate Path
if (!Directory.Exists(path))
return;

// Get DLLs in Directory
var files = Directory.GetFiles(path, "*.dll", SearchOption.TopDirectoryOnly);
foreach (var f in files)
{
// Ignore Native DLLs
if (!MelonUtils.IsManagedDLL(f))
continue;

// Log
if (!hasWroteLine)
{
hasWroteLine = true;
MelonLogger.WriteLine(Color.Magenta);
}

// Load Assembly
var asm = MelonAssembly.LoadMelonAssembly(f, false);
if (asm == null)
continue;

// Queue Assembly for Melon Parsing
if (addToList)
melonAssemblies.Add(asm);
}
}

private static void ProcessFolder(eScanType scanType,
string path,
ref bool hasWroteLine,
Expand Down Expand Up @@ -156,13 +121,11 @@ private static void ProcessFolder(eScanType scanType,
Resolver.MelonAssemblyResolver.AddSearchDirectory(directory);

// Load UserLibs
foreach (var dir in userLibDirectories)
LoadFolder(dir, false, ref hasWroteLine, ref melonAssemblies);
MelonPreprocessor.LoadFolders(userLibDirectories, false, ref hasWroteLine, ref melonAssemblies);

// Load Melons from Folders
if (scanType != eScanType.UserLibs)
foreach (var dir in melonDirectories)
LoadFolder(dir, true, ref hasWroteLine, ref melonAssemblies);
MelonPreprocessor.LoadFolders(melonDirectories, true, ref hasWroteLine, ref melonAssemblies);
}

private static void ScanFolder(eScanType scanType,
Expand Down
95 changes: 95 additions & 0 deletions MelonLoader/Melons/MelonPreprocessor.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using Mono.Cecil;

namespace MelonLoader.Melons
{
internal static class MelonPreprocessor
{
internal static void LoadFolders(List<string> directoryPaths,
bool isMelon,
ref bool hasWroteLine,
ref List<MelonAssembly> melonAssemblies)
{
// Find All Assemblies
Dictionary<string, (Version, string)> foundAssemblies = new();
foreach (string path in directoryPaths)
PreprocessFolder(path, isMelon, ref foundAssemblies);

// Load from File Paths
foreach (var foundFile in foundAssemblies)
{
// Log
if (!hasWroteLine)
{
hasWroteLine = true;
MelonLogger.WriteLine(Color.Magenta);
}

// Load Assembly
var asm = MelonAssembly.LoadMelonAssembly(foundFile.Value.Item2, false);
if (asm == null)
continue;

// Queue Assembly for Melon Parsing
if (isMelon)
melonAssemblies.Add(asm);
}
}

private static void PreprocessFolder(string path,
bool isMelon,
ref Dictionary<string, (Version, string)> foundAssemblies)
{
// Validate Path
if (!Directory.Exists(path))
return;

// Get DLLs in Directory
var files = Directory.GetFiles(path, "*.dll", SearchOption.TopDirectoryOnly);
foreach (var f in files)
{
// Ignore Native DLLs
if (!MelonUtils.IsManagedDLL(f))
continue;

// Load Definition using Cecil
AssemblyDefinition asmDef = LoadDefinition(f);
if (asmDef == null)
continue;

// Pull Name and Version from AssemblyDefinitionName
string name = $"{asmDef.Name.Name}";
Version version = new(asmDef.Name.Version.ToString());

// Dispose of Definition
asmDef.Dispose();

// Check for Existing Version
if (foundAssemblies.TryGetValue(name, out (Version, string) existingVersion)
&& (existingVersion.Item1 >= version))
continue;

// Add File to List
foundAssemblies[name] = (version, f);
}
}

private static AssemblyDefinition LoadDefinition(string path)
{
path = Path.GetFullPath(path);

try
{
return AssemblyDefinition.ReadAssembly(path);
}
catch (Exception ex)
{
MelonLogger.Error($"Failed to load AssemblyDefinition from '{path}':\n{ex}");
return null;
}
}
}
}

0 comments on commit 41ed941

Please sign in to comment.