Skip to content

Commit

Permalink
Resources related optimization and debug
Browse files Browse the repository at this point in the history
  • Loading branch information
rube200 committed Oct 28, 2023
1 parent 54ae252 commit 49f2c5b
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 45 deletions.
22 changes: 5 additions & 17 deletions framework/OpenMod.Common/Hotloading/Hotloader.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using AsmResolver;
using AsmResolver.IO;
using AsmResolver.IO;
using AsmResolver.PE;
using AsmResolver.PE.DotNet;
using AsmResolver.PE.DotNet.Builder;
Expand Down Expand Up @@ -160,18 +159,14 @@ public static void Remove(Assembly assembly)
/// <returns><b>The hotloaded assembly</b> if found; otherwise, <b>null</b>.</returns>
public static Assembly? FindAssembly(AssemblyName name)
{
if (s_Assemblies.TryGetValue(name, out var assembly))
{
return assembly;
}

return null;
return s_Assemblies.TryGetValue(name, out var assembly) ? assembly : null;
}

/// <summary>
/// Gets all hotloaded assemblies.
/// </summary>
/// <returns>The hotloaded assemblies.</returns>
// ReSharper disable once UnusedMember.Global
public static IReadOnlyCollection<Assembly> GetHotloadedAssemblies()
{
return s_Assemblies.Values;
Expand All @@ -184,15 +179,8 @@ public static IReadOnlyCollection<Assembly> GetHotloadedAssemblies()
/// <returns><b>The real assembly name</b> of the hotloaded assembly. If the given assembly was not hotloaded, it will return <b>the assembly's name</b>.</returns>
public static AssemblyName GetRealAssemblyName(Assembly assembly)
{
foreach (var kv in s_Assemblies)
{
if (kv.Value == assembly)
{
return kv.Key;
}
}

return assembly.GetName();
var assemblyName = s_Assemblies.FirstOrDefault(kv => kv.Value == assembly).Key;
return assemblyName ?? assembly.GetName();
}
}
}
46 changes: 21 additions & 25 deletions framework/OpenMod.Core/Helpers/AssemblyHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,63 +23,59 @@ public static void CopyAssemblyResources(Assembly assembly, string? baseDir, boo
baseDir ??= string.Empty;

var resourceNames = assembly.GetManifestResourceNames();

if (resourceNames.Length > 0 && !Directory.Exists(baseDir))
{
Directory.CreateDirectory(baseDir);
}

var assemblyName = Hotloader.GetRealAssemblyName(assembly);
var assemblyNameDot = $"{assemblyName.Name}.";
var assemblyNameDotRegex = new Regex(Regex.Escape(assemblyNameDot));

Log.Debug("Found {ResourceNames.Length} resources for {AssemblyName}.", resourceNames, assemblyName.Name);

foreach (var resourceName in resourceNames)
{
if (resourceName.EndsWith("..directory"))
{
continue;
}

var assemblyName = Hotloader.GetRealAssemblyName(assembly);

if (!resourceName.Contains(assemblyName.Name + "."))
if (!resourceName.Contains(assemblyNameDot))
{
Log.Warning(
"{ResourceName} does not contain assembly name in assembly: {AssemblyName}. <AssemblyName> and <RootNamespace> must be equal inside your plugins .csproj file",
resourceName, assemblyName.Name);
}

var regex = new Regex(Regex.Escape(assemblyName.Name + "."));
var fileName = regex.Replace(resourceName, string.Empty, 1);

var fileName = assemblyNameDotRegex.Replace(resourceName, string.Empty, 1);
if (s_ExcludedResources.Contains(fileName))
{
continue;
}

var parts = fileName.Split('.');
fileName = "";
Log.Debug("Working on {ResourceName} resource with name {FileName.}", resourceName, fileName);

var fileNameParts = fileName.Split('.');
fileName = string.Empty;

var pathSb = new StringBuilder(assemblyName.Name + ".");
foreach (var part in parts)
var fileNameSb = new StringBuilder(assemblyNameDot);
var pathSb = new StringBuilder(assemblyNameDot);

foreach (var part in fileNameParts)
{
pathSb.Append(part + ".");
var partDot = $"{part}.";
pathSb.Append(partDot);

using var tmpStream = assembly.GetManifestResourceStream(pathSb + ".directory");

var isDirectory = tmpStream != null;
if (isDirectory)
{
fileName += part + Path.DirectorySeparatorChar;
}
else
{
fileName += part + ".";
}
fileNameSb.Append(isDirectory ? $"{part}{Path.DirectorySeparatorChar}" : partDot);
}

if (fileName.EndsWith("."))
{
fileName = fileName.Substring(0, fileName.Length - 1);
}
fileName = fileNameSb[^1] == '.' ? fileNameSb.ToString(0, fileName.Length - 1) : fileNameSb.ToString();

var directory = Path.GetDirectoryName(fileName);

if (directory != null)
{
directory = Path.Combine(baseDir, directory);
Expand Down
16 changes: 13 additions & 3 deletions framework/OpenMod.Core/Plugins/PluginAssemblyStore.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public class PluginAssemblyStore : IPluginAssemblyStore, IDisposable
private readonly NuGetPackageManager m_NuGetPackageManager;

/// <summary>
/// Defines if openmod would try to install missing dependencies.
/// Defines if OpenMod would try to install missing dependencies.
/// </summary>
public static bool TryInstallMissingDependencies { get; set; }

Expand Down Expand Up @@ -63,9 +63,18 @@ public IReadOnlyCollection<Assembly> LoadedPluginAssemblies
{
var packagesResourceName = assembly.GetManifestResourceNames()
.FirstOrDefault(x => x.EndsWith("packages.yaml"));
if (packagesResourceName == null) return newPlugins;
if (packagesResourceName == null)
return newPlugins;

var packagesRosourceInfo = assembly.GetManifestResourceInfo(packagesResourceName);
m_Logger.LogDebug("Found packages.yaml with name {PackagesResourceName}.", packagesResourceName);
m_Logger.LogDebug("Package resource info {PackagesRosourceInfo}.", packagesRosourceInfo);

#if NETSTANDARD2_1_OR_GREATER
await using var stream = assembly.GetManifestResourceStream(packagesResourceName);
#else
using var stream = assembly.GetManifestResourceStream(packagesResourceName);
#endif
if (stream == null) return newPlugins;

using var reader = new StreamReader(stream);
Expand All @@ -91,6 +100,7 @@ public IReadOnlyCollection<Assembly> LoadedPluginAssemblies

var newAssemblies = m_NuGetPackageManager.GetLoadedAssemblies().Except(existingPackages);

// ReSharper disable once LoopCanBeConvertedToQuery
foreach (var newAssembly in newAssemblies.Select(x => (Assembly)x.Assembly.Target))
{
if (newAssembly == null) continue;
Expand Down Expand Up @@ -171,7 +181,7 @@ public async Task<ICollection<Assembly>> LoadPluginAssembliesAsync(IPluginAssemb
continue;
}

if (types.Any(d => d.GetInterfaces().Any(x => x == typeof(IOpenModPlugin)) && !d.IsAbstract && d.IsClass))
if (types.Any(d => d.GetInterfaces().Any(x => x == typeof(IOpenModPlugin)) && d is { IsAbstract: false, IsClass: true }))
{
continue;
}
Expand Down

0 comments on commit 49f2c5b

Please sign in to comment.