diff --git a/Barotrauma/BarotraumaShared/Luatrauma.props b/Barotrauma/BarotraumaShared/Luatrauma.props
index ebc46700a..a17acc078 100644
--- a/Barotrauma/BarotraumaShared/Luatrauma.props
+++ b/Barotrauma/BarotraumaShared/Luatrauma.props
@@ -7,7 +7,7 @@
-
+
diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Data/DataInterfaceImplementations.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Data/DataInterfaceImplementations.cs
index 274d41c0c..514188b3f 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Data/DataInterfaceImplementations.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Data/DataInterfaceImplementations.cs
@@ -43,6 +43,7 @@ public record AssemblyResourceInfo : BaseResourceInfo, IAssemblyResourceInfo
{
public string FriendlyName { get; init; }
public bool IsScript { get; init; }
+ public bool UseInternalAccessName { get; init; }
}
///
diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Data/IResourceInfoDeclarations.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Data/IResourceInfoDeclarations.cs
index 366578fdb..f40850cfa 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Data/IResourceInfoDeclarations.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Data/IResourceInfoDeclarations.cs
@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Globalization;
+using System.Runtime.CompilerServices;
namespace Barotrauma.LuaCs.Data;
@@ -31,6 +32,12 @@ public interface IAssemblyResourceInfo : IBaseResourceInfo
/// Is this entry referring to a script file collection.
///
public bool IsScript { get; }
+
+ ///
+ /// [Required(IsScript: true)] Whether the internal compiled assembly name should be named to enabled use of the
+ /// attribute.
+ ///
+ public bool UseInternalAccessName { get; }
}
diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs
index 223e83ba0..1d32ce229 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs
@@ -22,6 +22,7 @@ using FluentResults;
using ImpromptuInterface;
using LightInject;
using Microsoft.Toolkit.Diagnostics;
+using AssemblyLoader = Barotrauma.LuaCs.Services.AssemblyLoader;
namespace Barotrauma
{
@@ -185,6 +186,7 @@ namespace Barotrauma
servicesProvider.RegisterServiceResolver(factory => factory.GetInstance() as ILuaCsHook);
servicesProvider.RegisterServiceType(ServiceLifetime.Singleton);
servicesProvider.RegisterServiceType(ServiceLifetime.Singleton);
+ servicesProvider.RegisterServiceType(ServiceLifetime.Transient);
servicesProvider.RegisterServiceResolver(factory => factory.GetInstance());
servicesProvider.RegisterServiceType(ServiceLifetime.Singleton);
servicesProvider.RegisterServiceType(ServiceLifetime.Transient);
diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/LoggerService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/LoggerService.cs
index fc5e23586..f0bfc110a 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/LoggerService.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/LoggerService.cs
@@ -182,7 +182,7 @@ public partial class LoggerService : ILoggerService
return;
}
- if (result.Errors.Any())
+ if (result.IsFailed)
{
foreach (var error in result.Errors)
{
@@ -192,7 +192,7 @@ public partial class LoggerService : ILoggerService
}
else
{
- LogError(error.Message);
+ LogError($"FluentResults::IError: {error.Message}");
}
diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PackageManagementService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PackageManagementService.cs
index 65ad767df..c26a38e83 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PackageManagementService.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PackageManagementService.cs
@@ -261,7 +261,9 @@ public sealed class PackageManagementService : IPackageManagementService
return result;
}
- private static ImmutableArray SelectCompatible(ImmutableArray resources, ImmutableHashSet enabledPackagesIdents, ImmutableArray loadingOrder)
+ private static ImmutableArray SelectCompatible(ImmutableArray resources,
+ ImmutableHashSet enabledPackagesIdents,
+ ImmutableArray loadingOrder)
where T : IBaseResourceInfo
{
return resources
@@ -289,14 +291,22 @@ public sealed class PackageManagementService : IPackageManagementService
var result = new FluentResults.Result();
- result.WithReasons(UnloadPackages(toRemove).Reasons);
+ if (!toRemove.IsDefaultOrEmpty)
+ {
+ result.WithReasons(UnloadPackages(toRemove).Reasons);
+ }
if (result.IsFailed)
{
return result;
}
- return result.WithReasons(LoadPackagesInfo(toAdd).Reasons);
+ if (!toAdd.IsDefaultOrEmpty)
+ {
+ result.WithReasons(LoadPackagesInfo(toAdd).Reasons);
+ }
+
+ return result;
}
public FluentResults.Result StopRunningPackages()
diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PluginManagementService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PluginManagementService.cs
index 6bc10f0d6..63b9e3a51 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PluginManagementService.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PluginManagementService.cs
@@ -7,114 +7,124 @@ using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Loader;
+using System.Text;
using System.Threading;
using Barotrauma.Extensions;
+using Barotrauma.IO;
using Barotrauma.LuaCs.Data;
using Barotrauma.LuaCs.Events;
using FluentResults;
using FluentResults.LuaCs;
using ImpromptuInterface.Build;
using Microsoft.CodeAnalysis;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.Text;
+using Microsoft.Extensions.Logging;
using Microsoft.Toolkit.Diagnostics;
using OneOf;
namespace Barotrauma.LuaCs.Services;
-public class PluginManagementService : IPluginManagementService, IAssemblyManagementService
+public class PluginManagementService : IAssemblyManagementService
{
- private readonly Func _assemblyLoaderServiceFactory;
- private readonly ConcurrentDictionary ResourceInfos, IAssemblyLoaderService Loader)> _packageAssemblyResources = new();
- private readonly ConcurrentDictionary> _pluginInstances = new();
- private readonly Lazy _eventService;
- private readonly ConditionalWeakTable _unloadingAssemblyLoaders = new();
- private readonly ConditionalWeakTable> _assemblyTypesCache = new();
+ #region CSHARP_COMPILATION_OPTIONS
- public PluginManagementService(
- Func assemblyLoaderServiceFactory,
- Lazy eventService)
- {
- _assemblyLoaderServiceFactory = assemblyLoaderServiceFactory;
- _eventService = eventService;
- AppDomain.CurrentDomain.AssemblyLoad += OnAssemblyLoadedGlobal;
- }
-
- private void OnAssemblyLoadedGlobal(object sender, AssemblyLoadEventArgs args)
- {
- // cache types by name
- try
+ private static readonly CSharpParseOptions ScriptParseOptions = CSharpParseOptions.Default
+ .WithPreprocessorSymbols(new[]
{
- var context = AssemblyLoadContext.GetLoadContext(args.LoadedAssembly);
- if (context is not IAssemblyLoaderService loaderService)
- return;
- _eventService.Value.PublishEvent(sub => sub.OnAssemblyLoaded(args.LoadedAssembly));
- var lookupDict = new ConcurrentDictionary();
- foreach (var type in args.LoadedAssembly.GetSafeTypes())
- {
- lookupDict[type.FullName ?? type.Name] = type;
- }
- _assemblyTypesCache.AddOrUpdate(args.LoadedAssembly, lookupDict);
- }
- catch (Exception e)
- {
- // ignored
- return;
- }
- }
+#if SERVER
+ "SERVER"
+#elif CLIENT
+ "CLIENT"
+#else
+ "UNDEFINED"
+#endif
+#if DEBUG
+ ,"DEBUG"
+#endif
+ });
- private int _isDisposed = 0;
- public bool IsDisposed
- {
- get => ModUtils.Threading.GetBool(ref _isDisposed);
- private set => ModUtils.Threading.SetBool(ref _isDisposed, value);
- }
+#if WINDOWS
+ private const string PLATFORM_TARGET = "Windows";
+#elif OSX
+ private const string PLATFORM_TARGET = "OSX";
+#elif LINUX
+ private const string PLATFORM_TARGET = "Linux";
+#endif
+
+#if CLIENT
+ private const string ARCHITECTURE_TARGET = "Client";
+#elif SERVER
+ private const string ARCHITECTURE_TARGET = "Server";
+#endif
+
+ private static readonly CSharpCompilationOptions CompilationOptions = new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
+ .WithMetadataImportOptions(MetadataImportOptions.All)
+#if DEBUG
+ .WithOptimizationLevel(OptimizationLevel.Debug)
+#else
+ .WithOptimizationLevel(OptimizationLevel.Release)
+#endif
+ .WithAllowUnsafe(true);
+
+ private static readonly SyntaxTree BaseAssemblyImports = CSharpSyntaxTree.ParseText(
+ new StringBuilder()
+ .AppendLine("using System.Reflection;")
+ .AppendLine("using Barotrauma;")
+ .AppendLine("using System.Runtime.CompilerServices;")
+ .AppendLine("[assembly: IgnoresAccessChecksTo(\"BarotraumaCore\")]")
+#if CLIENT
+ .AppendLine("[assembly: IgnoresAccessChecksTo(\"Barotrauma\")]")
+#elif SERVER
+ .AppendLine("[assembly: IgnoresAccessChecksTo(\"DedicatedServer\")]")
+#endif
+ .ToString(),
+ ScriptParseOptions);
+
+ #endregion
+
+ #region Disposal
public void Dispose()
{
throw new NotImplementedException();
}
+ public bool IsDisposed { get; }
public FluentResults.Result Reset()
{
- if (IsDisposed)
- return FluentResults.Result.Fail($"{nameof(PluginManagementService)} is disposed!");
-
- return FluentResults.Result.Fail("not implemented");
+ throw new NotImplementedException();
}
- public Result> GetImplementingTypes(bool includeInterfaces = false,
- bool includeAbstractTypes = false, bool includeDefaultContext = true)
+ #endregion
+
+ private IServicesProvider _serviceProvider;
+ private IAssemblyLoaderService.IFactory _assemblyLoaderFactory;
+ private IStorageService _storageService;
+ private ILoggerService _logger;
+ private readonly ConcurrentDictionary _assemblyLoaders = new();
+ private readonly AsyncReaderWriterLock _operationsLock = new();
+
+ public PluginManagementService(
+ IServicesProvider serviceProvider,
+ IAssemblyLoaderService.IFactory assemblyLoaderFactory,
+ IStorageService storageService,
+ ILoggerService logger)
{
- var builder = ImmutableArray.CreateBuilder();
-
- if (this._packageAssemblyResources.Any())
- {
- foreach (var resource in this._packageAssemblyResources
- .Where(res => !res.Value.Loader.IsReferenceOnlyMode))
- {
- builder.AddRange(resource.Value.Loader.Assemblies
- .SelectMany(assembly => assembly.GetSafeTypes())
- .Where(type => type.IsAssignableTo(typeof(T)))
- .Where(type => includeInterfaces || !type.IsInterface)
- .Where(type => includeAbstractTypes || !type.IsAbstract));
- }
- }
-
- if (includeDefaultContext)
- {
- builder.AddRange(AssemblyLoadContext.Default.Assemblies
- .SelectMany(assembly => assembly.GetSafeTypes())
- .Where(type => type.IsAssignableTo(typeof(T)))
- .Where(type => includeInterfaces || !type.IsInterface)
- .Where(type => includeAbstractTypes || !type.IsAbstract));
- }
-
- return builder.Count == 0
- ? FluentResults.Result.Fail($"Failed to find any types that implement {typeof(T).Name})")
- : FluentResults.Result.Ok(builder.ToImmutable());
+ Guard.IsNotNull(serviceProvider, nameof(serviceProvider));
+ _serviceProvider = serviceProvider;
+ _assemblyLoaderFactory = assemblyLoaderFactory;
+ _storageService = storageService;
+ _logger = logger;
}
- public Type GetType(string typeName, bool isByRefType = false, bool includeInterfaces = true,
+ public Result> GetImplementingTypes(bool includeInterfaces = false, bool includeAbstractTypes = false,
+ bool includeDefaultContext = true)
+ {
+ throw new NotImplementedException();
+ }
+
+ public Type GetType(string typeName, bool isByRefType = false, bool includeInterfaces = false,
bool includeDefaultContext = true)
{
if (includeDefaultContext)
@@ -144,91 +154,197 @@ public class PluginManagementService : IPluginManagementService, IAssemblyManage
return null;
}
- public FluentResults.Result LoadAssemblyResources(ImmutableArray resources)
- {
- IService.CheckDisposed(this);
- if (resources.IsDefaultOrEmpty)
- {
- ThrowHelper.ThrowArgumentNullException($"{nameof(LoadAssemblyResources)}: The resources list is empty!");
- }
-
- return FluentResults.Result.Fail("not implemented");
- }
-
public ImmutableArray> ActivateTypeInstances(ImmutableArray types, bool serviceInjection = true,
bool hostInstanceReference = false) where T : IDisposable
{
+ throw new NotImplementedException();
+ }
+
+ public FluentResults.Result LoadAssemblyResources(ImmutableArray resources)
+ {
+ if (resources.IsDefaultOrEmpty)
+ {
+ ThrowHelper.ThrowArgumentNullException($"{nameof(LoadAssemblyResources)} The resource list is empty.)");
+ }
+ using var lck = _operationsLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult();
+ IService.CheckDisposed(this);
+
+ var orderedContentPacks = resources.GroupBy(res => res.OwnerPackage)
+ .OrderBy(res => resources.FindIndex(r2 => r2.OwnerPackage == res.Key))
+ .ToImmutableArray();
+
+ var result = new FluentResults.Result();
+
+ return FluentResults.Result.Fail($"{nameof(LoadAssemblyResources)}: Not Implemented!");
+ throw new NotImplementedException();
+
+ foreach (var contentPack in orderedContentPacks)
+ {
+ LoadBinaries(contentPack);
+ LoadAndCompileScriptAssemblies(contentPack);
+ }
+
+ return result;
+
+ // helper methods
+ void LoadBinaries(IGrouping contentPackRes)
+ {
+ var binaries = contentPackRes.Where(cRes => !cRes.IsScript)
+ .OrderBy(bin => bin.LoadPriority)
+ .SelectMany(bin => bin.FilePaths)
+ .ToImmutableArray();
+
+ if (binaries.IsDefaultOrEmpty)
+ {
+ return;
+ }
+
+ var assemblyLoader = _assemblyLoaders.GetOrAdd(contentPackRes.Key, (cp) => _assemblyLoaderFactory.CreateInstance(
+ new IAssemblyLoaderService.LoaderInitData(
+ InstanceId: Guid.NewGuid(),
+ contentPackRes.Key.Name,
+ IsReferenceMode: false,
+ OwnerPackage: contentPackRes.Key,
+ OnUnload: OnAssemblyLoaderUnloading,
+ OnResolvingManaged: OnAssemblyLoaderResolvingManaged,
+ OnResolvingUnmanagedDll: OnAssemblyLoaderResolvingUnmanaged
+ )));
+
+ var dependencyPaths = binaries
+ .Select(bin => System.IO.Path.GetDirectoryName(bin.FullPath))
+ .Distinct()
+ .ToImmutableArray();
+
+ foreach (var binResource in binaries)
+ {
+ var res = assemblyLoader.LoadAssemblyFromFile(binResource.FullPath, dependencyPaths);
+ result.WithReasons(res.Reasons);
#if DEBUG
- return ImmutableArray>.Empty;
+ _logger.LogResults(res.ToResult());
#endif
+ if (res.IsFailed)
+ {
+ _logger.LogResults(res.ToResult());
+ }
+ }
+ }
+
+ void LoadAndCompileScriptAssemblies(IGrouping contentPackRes)
+ {
+ var scripts = contentPackRes.Where(cRes => cRes.IsScript)
+ .OrderBy(scr => scr.LoadPriority)
+ .Select(scr => (scr.FriendlyName, scr.FilePaths, scr.UseInternalAccessName))
+ .GroupBy(scr => scr.FriendlyName)
+ .ToImmutableArray();
+
+ if (scripts.IsDefaultOrEmpty)
+ {
+ return;
+ }
+
+ var metadataReferences = GetMetadataReferences();
+
+ var assemblyLoader = _assemblyLoaders.GetOrAdd(contentPackRes.Key, (cp) => _assemblyLoaderFactory.CreateInstance(
+ new IAssemblyLoaderService.LoaderInitData(
+ InstanceId: Guid.NewGuid(),
+ contentPackRes.Key.Name,
+ IsReferenceMode: false,
+ OwnerPackage: contentPackRes.Key,
+ OnUnload: OnAssemblyLoaderUnloading,
+ OnResolvingManaged: OnAssemblyLoaderResolvingManaged,
+ OnResolvingUnmanagedDll: OnAssemblyLoaderResolvingUnmanaged
+ )));
+
+ // create syntax trees
+ var syntaxTreesBuilder = ImmutableArray.CreateBuilder();
+
+ foreach (var resourceInfo in contentPackRes)
+ {
+ if (resourceInfo.FilePaths.IsDefaultOrEmpty)
+ {
+ ThrowHelper.ThrowArgumentNullException($"{nameof(LoadAndCompileScriptAssemblies)} The resource list is empty for package {resourceInfo.OwnerPackage}.");
+ }
+
+ var loadRes = GetSourceFilesText(resourceInfo.FilePaths);
+ if (loadRes.IsFailed)
+ {
+ _logger.LogResults(loadRes.ToResult());
+ continue;
+ }
+
+ CancellationToken token = CancellationToken.None;
+
+ syntaxTreesBuilder.Add(SyntaxFactory.ParseSyntaxTree(
+ text: loadRes.Value,
+ options: ScriptParseOptions,
+ path: null,
+ encoding: Encoding.Default,
+ cancellationToken: token
+ ));
+ }
+
+ throw new NotImplementedException();
+ }
+
+ Result GetSourceFilesText(ImmutableArray resourceInfoFilePaths)
+ {
+ if (_storageService.LoadPackageTextFiles(resourceInfoFilePaths) is not { IsDefaultOrEmpty: false } res)
+ {
+ _logger.LogError($"{nameof(GetSourceFilesText)}: Failed to load source files for ContentPackage {resourceInfoFilePaths.First().ContentPackage?.Name}.");
+ return FluentResults.Result.Fail($"{nameof(GetSourceFilesText)}: Failed to load source files for ContentPackage {resourceInfoFilePaths.First().ContentPackage?.Name}.");
+ }
+
+ var loadRes = new FluentResults.Result();
+ StringBuilder sb = new StringBuilder();
+
+ foreach ((ContentPath Path, Result FileResult) loadResult in res)
+ {
+ if (loadResult.FileResult.IsFailed)
+ {
+ loadRes.WithErrors(loadResult.FileResult.Errors);
+ continue;
+ }
+
+ sb.AppendLine(loadResult.FileResult.Value);
+ }
+
+ if (loadRes.IsFailed)
+ {
+ return loadRes;
+ }
+
+ return sb.ToString();
+ }
+
+ IEnumerable GetMetadataReferences()
+ {
+ return Basic.Reference.Assemblies.Net80.References.All;
+ }
+ }
+
+ private IntPtr OnAssemblyLoaderResolvingUnmanaged(Assembly arg1, string arg2)
+ {
+ throw new NotImplementedException();
+ }
+
+ private Assembly OnAssemblyLoaderResolvingManaged(IAssemblyLoaderService arg1, AssemblyName arg2)
+ {
+ throw new NotImplementedException();
+ }
+
+ private void OnAssemblyLoaderUnloading(IAssemblyLoaderService loader)
+ {
throw new NotImplementedException();
}
public FluentResults.Result UnloadManagedAssemblies()
{
- var res = new FluentResults.Result();
-
- // cleanup managed plugins
- if (_pluginInstances.Any())
- {
- foreach (var packageInstances in _pluginInstances)
- {
- if (!packageInstances.Value.Any())
- continue;
-
- foreach (var disposable in packageInstances.Value)
- {
- try
- {
- disposable.Dispose();
- }
- catch (Exception e)
- {
- res = res.WithError(new ExceptionalError(e)
- .WithMetadata(MetadataType.ExceptionObject, this));
- }
- }
- }
- _pluginInstances.Clear();
- }
-
- _assemblyTypesCache.Clear();
-
- // cleanup running assembly contexts
- if (_packageAssemblyResources.Any())
- {
- foreach (var resource in _packageAssemblyResources.ToImmutableDictionary())
- {
- if (resource.Value.Loader is not null)
- {
- try
- {
- resource.Value.Loader.Dispose();
- _unloadingAssemblyLoaders.AddOrUpdate(resource.Value.Loader, resource.Key);
- _packageAssemblyResources.TryRemove(resource);
- _packageAssemblyResources.TryAdd(resource.Key, (resource.Value.ResourceInfos, null));
- }
- catch (Exception e)
- {
- res = res.WithError(new ExceptionalError(e)
- .WithMetadata(MetadataType.ExceptionObject, this));
- }
- }
- }
- }
-
- return res.WithSuccess($"Unloading of managed assemblies started successfully,");
+ return FluentResults.Result.Fail($"{nameof(UnloadManagedAssemblies)}: Not Implemented.");
+ throw new NotImplementedException();
}
public Result GetLoadedAssembly(OneOf assemblyName, in Guid[] excludedContexts)
{
throw new NotImplementedException();
}
-
- public ImmutableArray GetDefaultMetadataReferences(bool includeDefaultContext = true)
- {
- throw new NotImplementedException();
- }
-
- public ImmutableArray AssemblyLoaderServices { get; }
}
diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Processing/ModConfigFileParserService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Processing/ModConfigFileParserService.cs
index 3f9b5ef25..b35212eae 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Processing/ModConfigFileParserService.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/Processing/ModConfigFileParserService.cs
@@ -79,6 +79,7 @@ public sealed class ModConfigFileParserService :
// Type Specific
FriendlyName = src.Element.GetAttributeString("FriendlyName", string.Empty),
IsScript = src.Element.GetAttributeBool("IsScript", false),
+ UseInternalAccessName = src.Element.GetAttributeBool("UseInternalAccessName", false)
};
}
diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/ServicesProvider.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/ServicesProvider.cs
index 37e454431..d0a81f425 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/ServicesProvider.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/ServicesProvider.cs
@@ -21,6 +21,8 @@ public class ServicesProvider : IServicesProvider
{
EnablePropertyInjection = false
});
+
+ _serviceContainerInst.Register((f) => this);
}
public void RegisterServiceType(ServiceLifetime lifetime, ILifetime lifetimeInstance = null) where TSvcInterface : class, IService where TService : class, IService, TSvcInterface
diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IAssemblyManagementService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IAssemblyManagementService.cs
index 2499d55f8..d82105455 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IAssemblyManagementService.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IAssemblyManagementService.cs
@@ -12,7 +12,7 @@ using OneOf;
namespace Barotrauma.LuaCs.Services;
-public interface IAssemblyManagementService : IReusableService
+public interface IAssemblyManagementService : IPluginManagementService
{
///
@@ -22,17 +22,4 @@ public interface IAssemblyManagementService : IReusableService
/// Guids of excluded contexts.
/// On Success: The assembly.
On Failure: nothing.
FluentResults.Result GetLoadedAssembly(OneOf assemblyName, in Guid[] excludedContexts);
-
- ///
- /// Gets all for all service-managed assemblies.
- ///
- /// collection for all service-managed, and default if selected, assemblies, if any are found. Returns an empty collection otherwise.
- ImmutableArray GetDefaultMetadataReferences(bool includeDefaultContext = true);
-
- ///
- /// Returns all active, managed assembly loaders.
- ///
- ImmutableArray AssemblyLoaderServices { get; }
-
-
}
diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IPluginManagementService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IPluginManagementService.cs
index 700418bfb..83cd59981 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IPluginManagementService.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IPluginManagementService.cs
@@ -32,13 +32,6 @@ public interface IPluginManagementService : IReusableService
///
Type GetType(string typeName, bool isByRefType = false, bool includeInterfaces = false, bool includeDefaultContext = true);
- ///
- /// Loads the provided assembly resources in the order of their dependencies and intra-mod priority load order.
- ///
- ///
- /// Success/Failure and list of failed resources, if any.
- FluentResults.Result LoadAssemblyResources(ImmutableArray resources);
-
///
/// Creates instances of the given type and provides Property Injection and instance reference caching. Disposes of
/// all references that throw errors on
@@ -50,6 +43,12 @@ public interface IPluginManagementService : IReusableService
ImmutableArray> ActivateTypeInstances(ImmutableArray types, bool serviceInjection = true,
bool hostInstanceReference = false) where T : IDisposable;
+ ///
+ /// Loads the provided assembly resources in the order of their dependencies and intra-mod priority load order.
+ ///
+ ///
+ /// Success/Failure and list of failed resources, if any.
+ FluentResults.Result LoadAssemblyResources(ImmutableArray resources);
///
/// Unloads all managed , , and s.
diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Plugins/AssemblyLoader.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Plugins/AssemblyLoader.cs
index a7cebbd5c..7a82c8494 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Plugins/AssemblyLoader.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Plugins/AssemblyLoader.cs
@@ -24,6 +24,20 @@ using Path = System.IO.Path;
namespace Barotrauma.LuaCs.Services;
public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
{
+ public class Factory : IAssemblyLoaderService.IFactory
+ {
+ public IAssemblyLoaderService CreateInstance(IAssemblyLoaderService.LoaderInitData initData)
+ {
+ return new AssemblyLoader(initData);
+ }
+
+ public void Dispose()
+ {
+ //stateless service
+ }
+ public bool IsDisposed => false;
+ }
+
public Guid Id { get; init; }
public ContentPackage OwnerPackage { get; private set; }
public bool IsReferenceOnlyMode { get; init; }
@@ -55,7 +69,6 @@ public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
private int _operationsRunning;
//internal
- private readonly IAssemblyManagementService _assemblyManagementService;
private readonly Action _onUnload;
private readonly Func _onResolvingManaged;
private readonly Func _onResolvingUnmanagedDll;
@@ -68,7 +81,6 @@ public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
public AssemblyLoader(IAssemblyLoaderService.LoaderInitData initData)
: base(isCollectible: true, name: initData.Name)
{
- _assemblyManagementService = initData.AssemblyManagementService;
Id = initData.InstanceId;
IsReferenceOnlyMode = initData.IsReferenceMode;
this._onUnload = initData.OnUnload;
@@ -217,7 +229,10 @@ public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
try
{
var p = Path.GetFullPath(path.CleanUpPath());
- _dependencyResolvers[p] = new AssemblyDependencyResolver(p);
+ if (!_dependencyResolvers.ContainsKey(p))
+ {
+ _dependencyResolvers[p] = new AssemblyDependencyResolver(p);
+ }
}
catch (Exception ex)
{
diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Plugins/IAssemblyLoaderService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Plugins/IAssemblyLoaderService.cs
index 071effa1a..c3dd6983a 100644
--- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Plugins/IAssemblyLoaderService.cs
+++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Plugins/IAssemblyLoaderService.cs
@@ -13,6 +13,11 @@ namespace Barotrauma.LuaCs;
public interface IAssemblyLoaderService : IService
{
+ public interface IFactory : IService
+ {
+ IAssemblyLoaderService CreateInstance(LoaderInitData initData);
+ }
+
///
/// Constructor record for instancing.
///
@@ -26,7 +31,6 @@ public interface IAssemblyLoaderService : IService
///
///
public record LoaderInitData(
- [Required][NotNull] IAssemblyManagementService AssemblyManagementService,
[Required] Guid InstanceId,
[Required][NotNull] string Name,
[Required] bool IsReferenceMode,