Skip to content

Commit

Permalink
fix: Fixes assembly loading. (#759)
Browse files Browse the repository at this point in the history
* `AssemblyHandler.Assemblies` will now only contain assemblies listed in `assemblies.json`
* `assemblies.json` has been updated to only contain asssemblies directly loaded by the server. Namely, only `UOContent.dll`.
  * Specifically assemblies loaded by assemblies.json are subject to check for `Configure` and `Initialize` methods.
* `modernuo.json` now has a new property called `assemblyDirectories`. This will be automatically set to `Distribution/Assemblies` (absolute path on your machine).
  * You can add more directories to this list.
* All assemblies in assemblies.json _AND_ dependents of any assembly will be searched for in the directories specified by `assemblyDirectories`.
  • Loading branch information
kamronbatman authored Sep 4, 2021
1 parent 0d1fffd commit 54e56d2
Show file tree
Hide file tree
Showing 5 changed files with 67 additions and 9 deletions.
6 changes: 0 additions & 6 deletions Distribution/Data/assemblies.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
[
"Argon2.Bindings.dll",
"BouncyCastle.Crypto.dll",
"MailKit.dll",
"MimeKit.dll",
"Microsoft.Extensions.FileSystemGlobbing.dll",
"Zlib.Bindings.dll",
"UOContent.dll"
]
62 changes: 60 additions & 2 deletions Projects/Server/AssemblyHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,71 @@ public static class AssemblyHandler
private static TypeCache m_NullCache;
public static Assembly[] Assemblies { get; set; }

public static void LoadScripts(string[] files)
internal static Assembly AssemblyResolver(object sender, ResolveEventArgs args) =>
LoadAssemblyByAssemblyName(args.Name);

private static void EnsureAssemblyDirectories()
{
if (ServerConfiguration.AssemblyDirectories.Count == 0)
{
ServerConfiguration.AssemblyDirectories.Add(Path.Combine(Core.BaseDirectory, "Assemblies"));
ServerConfiguration.Save();
}
}

public static Assembly LoadAssemblyByAssemblyName(string fullAssemblyName)
{
var assemblyName = new AssemblyName(fullAssemblyName);
var assemblyFile = $"{assemblyName.Name}.dll";

EnsureAssemblyDirectories();
var assemblyDirectories = ServerConfiguration.AssemblyDirectories;

foreach (var assemblyDir in assemblyDirectories)
{
var assemblyPath = Path.Combine(assemblyDir, assemblyFile);
if (File.Exists(assemblyPath))
{
var assemblyNameCheck = AssemblyName.GetAssemblyName(assemblyPath);
if (assemblyNameCheck.FullName == assemblyName.FullName)
{
return AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath);
}
}
}

return null;
}

public static Assembly LoadAssemblyByFileName(string assemblyFile)
{
EnsureAssemblyDirectories();
var assemblyDirectories = ServerConfiguration.AssemblyDirectories;

foreach (var assemblyDir in assemblyDirectories)
{
var assemblyPath = Path.Combine(assemblyDir, assemblyFile);
if (File.Exists(assemblyPath))
{
return AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath);
}
}

return null;
}

public static void LoadAssemblies(string[] files)
{
var assemblies = new Assembly[files.Length];

for (var i = 0; i < files.Length; i++)
{
assemblies[i] = AssemblyLoadContext.Default.LoadFromAssemblyPath(files[i]);
var assembly = LoadAssemblyByFileName(files[i]);
if (assembly == null)
{
throw new FileNotFoundException($"Could not load {files[i]}");
}
assemblies[i] = LoadAssemblyByFileName(files[i]);
}

Assemblies = assemblies;
Expand Down
2 changes: 2 additions & 0 deletions Projects/Server/Configuration/ServerConfiguration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public static class ServerConfiguration
private static ServerSettings m_Settings;
private static bool m_Mocked;

public static List<string> AssemblyDirectories => m_Settings.AssemblyDirectories;

public static List<string> DataDirectories => m_Settings.DataDirectories;

public static List<IPEndPoint> Listeners => m_Settings.Listeners;
Expand Down
3 changes: 3 additions & 0 deletions Projects/Server/Configuration/ServerSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ namespace Server
{
public class ServerSettings
{
[JsonPropertyName("assemblyDirectories")]
public List<string> AssemblyDirectories { get; set; } = new();

[JsonPropertyName("dataDirectories")]
public List<string> DataDirectories { get; set; } = new();

Expand Down
3 changes: 2 additions & 1 deletion Projects/Server/Main.cs
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,7 @@ public static void Main(string[] args)
{
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit;
AppDomain.CurrentDomain.AssemblyResolve += AssemblyHandler.AssemblyResolver;

LoopContext = new EventLoopContext();

Expand Down Expand Up @@ -463,7 +464,7 @@ You should have received a copy of the GNU General Public License
assemblyFiles[i] = Path.Join(BaseDirectory, "Assemblies", assemblyFiles[i]);
}

AssemblyHandler.LoadScripts(assemblyFiles);
AssemblyHandler.LoadAssemblies(assemblyFiles);

VerifySerialization();

Expand Down

0 comments on commit 54e56d2

Please sign in to comment.