- Added publicized assemblies to LuaCsForBarotrauma package via ModConfig.xml
- Added XmlAttribute tags for ModConfig.xml defined properties. - GetType and GetImplementingTypes<T> rework.
This commit is contained in:
@@ -2,4 +2,7 @@
|
||||
<ModConfig>
|
||||
<Lua File="%ModDir%/Lua/LuaSetup.lua" IsAutorun="true" />
|
||||
<Config File="%ModDir%/Config/SettingsShared.xml"/>
|
||||
<Assembly File="%ModDir%/Publicized/BarotraumaCore.dll" IsReferenceModeOnly="true"/>
|
||||
<Assembly File="%ModDir%/Publicized/Barotrauma.dll" Target="Client" IsReferenceModeOnly="true"/>
|
||||
<Assembly File="%ModDir%/Publicized/DedicatedServer.dll" Target="Server" IsReferenceModeOnly="true"/>
|
||||
</ModConfig>
|
||||
|
||||
@@ -6,6 +6,7 @@ using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Xml.Linq;
|
||||
using System.Xml.Serialization;
|
||||
using Barotrauma.LuaCs;
|
||||
using Barotrauma.Steam;
|
||||
using OneOf;
|
||||
@@ -44,6 +45,7 @@ public record AssemblyResourceInfo : BaseResourceInfo, IAssemblyResourceInfo
|
||||
public string FriendlyName { get; init; }
|
||||
public bool IsScript { get; init; }
|
||||
public bool UseInternalAccessName { get; init; }
|
||||
public bool IsReferenceModeOnly { get; init; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -81,9 +83,12 @@ public record ConfigInfo : IConfigInfo
|
||||
|
||||
public record ConfigProfileInfo : IConfigProfileInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// Profile name.
|
||||
/// </summary>
|
||||
public string InternalName { get; init; }
|
||||
public ContentPackage OwnerPackage { get; init; }
|
||||
public IReadOnlyList<(string ConfigName, XElement Element)> ProfileValues { get; init; }
|
||||
public IReadOnlyList<(string SettingName, XElement Element)> ProfileValues { get; init; }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Collections.Immutable;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Globalization;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Barotrauma.LuaCs.Data;
|
||||
|
||||
@@ -24,12 +25,14 @@ public interface IPlatformInfo
|
||||
/// Platforms that these localization files should be loaded for.
|
||||
/// </summary>
|
||||
[Required]
|
||||
[XmlAttribute("Platform")]
|
||||
Platform SupportedPlatforms { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Targets that these localization files should be loaded for.
|
||||
/// </summary>
|
||||
[Required]
|
||||
[XmlAttribute("Target")]
|
||||
Target SupportedTargets { get; }
|
||||
}
|
||||
|
||||
@@ -44,6 +47,7 @@ public interface IResourceInfo : IPlatformInfo
|
||||
/// Specifies the loading order for all assets of the same type (ie. styles, assemblies, etc.) from
|
||||
/// the same <see cref="ContentPackage"/>. Lower number is higher priority, see <see cref="System.Linq.Enumerable.OrderBy{TSource,TKey}(IEnumerable{TSource}, Func{TSource,TKey})"/>
|
||||
/// </summary>
|
||||
[XmlAttribute("LoadPriority")]
|
||||
int LoadPriority { get; }
|
||||
|
||||
/// <summary>
|
||||
@@ -56,5 +60,6 @@ public interface IResourceInfo : IPlatformInfo
|
||||
/// Marks this resource as optional (ie. Cross-CP content). Setting this to true will allow the dependency system to
|
||||
/// try and order the loading but not fail if it runs into circular dependency issues.
|
||||
/// </summary>
|
||||
[XmlAttribute("Optional")]
|
||||
bool Optional { get; }
|
||||
}
|
||||
|
||||
@@ -5,5 +5,5 @@ namespace Barotrauma.LuaCs.Data;
|
||||
|
||||
public interface IConfigProfileInfo : IDataInfo
|
||||
{
|
||||
IReadOnlyList<(string ConfigName, XElement Element)> ProfileValues { get; }
|
||||
IReadOnlyList<(string SettingName, XElement Element)> ProfileValues { get; }
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Barotrauma.LuaCs.Data;
|
||||
|
||||
@@ -11,6 +12,7 @@ public interface IDataInfo : IEqualityComparer<IDataInfo>, IEquatable<IDataInfo>
|
||||
/// <summary>
|
||||
/// Internal name unique within the resources inside a package.
|
||||
/// </summary>
|
||||
[XmlAttribute("Name")]
|
||||
string InternalName { get; }
|
||||
/// <summary>
|
||||
/// The package this information belongs to.
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Immutable;
|
||||
using System.Globalization;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Barotrauma.LuaCs.Data;
|
||||
|
||||
@@ -18,6 +19,7 @@ public interface ILuaScriptResourceInfo : IBaseResourceInfo
|
||||
/// <summary>
|
||||
/// Should this script be run automatically.
|
||||
/// </summary>
|
||||
[XmlAttribute("IsAutorun")]
|
||||
public bool IsAutorun { get; }
|
||||
}
|
||||
|
||||
@@ -27,17 +29,27 @@ public interface IAssemblyResourceInfo : IBaseResourceInfo
|
||||
/// The friendly name of the assembly. Script files belonging to the same assembly should all have the same name.
|
||||
/// Legacy scripts will all be given the sanitized name of the Content Package they belong to.
|
||||
/// </summary>
|
||||
[XmlAttribute("FriendlyName")]
|
||||
public string FriendlyName { get; }
|
||||
/// <summary>
|
||||
/// Is this entry referring to a script file collection.
|
||||
/// </summary>
|
||||
[XmlAttribute("IsScript")]
|
||||
public bool IsScript { get; }
|
||||
|
||||
/// <summary>
|
||||
/// <b>[Required(IsScript: true)] Whether the internal compiled assembly name should be named to enabled use of the
|
||||
/// <see cref="InternalsVisibleToAttribute"/> attribute.</b>
|
||||
/// </summary>
|
||||
[XmlAttribute("UseInternalAccessName")]
|
||||
public bool UseInternalAccessName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Should the following resources only be used for Compilation MetadataReference.
|
||||
/// NOTE: Affects the entire package's assembly resources, meant for internal use only.
|
||||
/// </summary>
|
||||
[XmlAttribute("IsReferenceModeOnly")]
|
||||
public bool IsReferenceModeOnly { get; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -208,6 +208,10 @@ public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
|
||||
AreOperationRunning = true;
|
||||
foreach (var data in _loadedAssemblyData.Values)
|
||||
{
|
||||
if (data.AssemblyReference is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
yield return data.AssemblyReference;
|
||||
}
|
||||
AreOperationRunning = false;
|
||||
@@ -356,10 +360,10 @@ public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
|
||||
if (additionalDependencyPaths.Any())
|
||||
{
|
||||
var r = AddDependencyPaths(additionalDependencyPaths);
|
||||
if (!r.IsFailed)
|
||||
if (r.IsFailed)
|
||||
{
|
||||
// we have errors, loading may not work.
|
||||
return FluentResults.Result.Fail(new Error($"Failed to load dependency paths.")
|
||||
return FluentResults.Result.Fail(new Error($"Failed to load dependency paths for '{assemblyFilePath}' with paths: {additionalDependencyPaths.Aggregate((s, ac) => $"{ac}| P={s}")}.")
|
||||
.WithMetadata(MetadataType.ExceptionObject, this)
|
||||
.WithMetadata(MetadataType.RootObject, assemblyFilePath))
|
||||
.WithErrors(r.Errors);
|
||||
@@ -379,7 +383,7 @@ public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
|
||||
try
|
||||
{
|
||||
var assembly = LoadFromAssemblyPath(sanitizedFilePath);
|
||||
_loadedAssemblyData[assembly] = new AssemblyData(assembly, sanitizedFilePath);
|
||||
_loadedAssemblyData[assembly] = new AssemblyData(assembly, assembly.Location);
|
||||
return new Result<Assembly>().WithSuccess($"Loaded assembly '{assembly.GetName()}'").WithValue(assembly);
|
||||
}
|
||||
catch (FileNotFoundException fnfe)
|
||||
|
||||
@@ -79,7 +79,8 @@ 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)
|
||||
UseInternalAccessName = src.Element.GetAttributeBool("UseInternalAccessName", false),
|
||||
IsReferenceModeOnly = src.Element.GetAttributeBool("IsReferenceModeOnly", false)
|
||||
};
|
||||
}
|
||||
|
||||
@@ -211,8 +212,8 @@ public sealed class ModConfigFileParserService :
|
||||
private (Platform Platform, Target Target) GetRuntimeEnvironment(XElement element)
|
||||
{
|
||||
return (
|
||||
Platform: element.GetAttributeEnum("Platform", Platform.Windows | Platform.Linux | Platform.OSX),
|
||||
Target: element.GetAttributeEnum("Target", Target.Client | Target.Server));
|
||||
Platform: element.GetAttributeEnum("Platform", Platform.Any),
|
||||
Target: element.GetAttributeEnum("Target", Target.Any));
|
||||
}
|
||||
|
||||
private async Task<ImmutableArray<Result<T>>> TryParseGenericResourcesAsync<T>(IEnumerable<ResourceParserInfo> sources)
|
||||
|
||||
@@ -264,7 +264,8 @@ public sealed class ModConfigService : IModConfigService
|
||||
FriendlyName = $"{src.Name}.{searchPathways.SubFolder.Replace('/','.')}",
|
||||
IncompatiblePackages = ImmutableArray<Identifier>.Empty,
|
||||
RequiredPackages = ImmutableArray<Identifier>.Empty,
|
||||
IsScript = false
|
||||
IsScript = false,
|
||||
IsReferenceModeOnly = false
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -304,7 +305,8 @@ public sealed class ModConfigService : IModConfigService
|
||||
IncompatiblePackages = ImmutableArray<Identifier>.Empty,
|
||||
RequiredPackages = ImmutableArray<Identifier>.Empty,
|
||||
UseInternalAccessName = true,
|
||||
IsScript = true
|
||||
IsScript = true,
|
||||
IsReferenceModeOnly = false
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,6 +86,29 @@ public class PluginManagementService : IAssemblyManagementService
|
||||
.ToString(),
|
||||
ScriptParseOptions);
|
||||
|
||||
private ImmutableArray<MetadataReference> _baseMetadataReferences = ImmutableArray<MetadataReference>.Empty;
|
||||
private IEnumerable<MetadataReference> BaseMetadataReferences
|
||||
{
|
||||
get
|
||||
{
|
||||
if (_baseMetadataReferences.IsDefaultOrEmpty)
|
||||
{
|
||||
_baseMetadataReferences = Basic.Reference.Assemblies.Net80.References.All
|
||||
.Union(AssemblyLoadContext.Default.Assemblies
|
||||
.Where(ass =>
|
||||
!ass.IsDynamic &&
|
||||
!ass.GetName().FullName.EndsWith("Barotrauma.Core") &&
|
||||
!ass.GetName().FullName.EndsWith("Barotrauma") &&
|
||||
!ass.GetName().FullName.EndsWith("DedicatedServer"))
|
||||
.Select(MetadataReference (ass) => MetadataReference.CreateFromFile(ass.Location)))
|
||||
.Where(ar => ar is not null)
|
||||
.ToImmutableArray();
|
||||
}
|
||||
|
||||
return _baseMetadataReferences;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Disposal
|
||||
@@ -213,14 +236,35 @@ public class PluginManagementService : IAssemblyManagementService
|
||||
public Result<ImmutableArray<Type>> GetImplementingTypes<T>(bool includeInterfaces = false, bool includeAbstractTypes = false,
|
||||
bool includeDefaultContext = true)
|
||||
{
|
||||
#if !DEBUG
|
||||
throw new NotImplementedException();
|
||||
#endif
|
||||
if (includeInterfaces)
|
||||
{
|
||||
includeAbstractTypes = true;
|
||||
}
|
||||
|
||||
using var lck = _operationsLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
IService.CheckDisposed(this);
|
||||
|
||||
var builder = ImmutableArray.CreateBuilder<Type>();
|
||||
|
||||
foreach (var ass in AppDomain.CurrentDomain.GetAssemblies())
|
||||
if (includeDefaultContext)
|
||||
{
|
||||
foreach (var type in ass.GetSafeTypes())
|
||||
foreach (var ass in AssemblyLoadContext.Default.Assemblies)
|
||||
{
|
||||
AddTypesFromAssembly(ass);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var ass in _assemblyLoaders.Values.Where(al => !al.IsReferenceOnlyMode).SelectMany(al => al.Assemblies))
|
||||
{
|
||||
AddTypesFromAssembly(ass);
|
||||
}
|
||||
|
||||
return builder.ToImmutable();
|
||||
|
||||
|
||||
void AddTypesFromAssembly(Assembly assembly)
|
||||
{
|
||||
foreach (var type in assembly.GetSafeTypes())
|
||||
{
|
||||
if ((includeInterfaces || !type.IsInterface)
|
||||
&& (includeAbstractTypes || !type.IsAbstract)
|
||||
@@ -230,8 +274,6 @@ public class PluginManagementService : IAssemblyManagementService
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return builder.ToImmutable();
|
||||
}
|
||||
|
||||
public Type GetType(string typeName, bool isByRefType = false, bool includeInterfaces = false,
|
||||
@@ -255,9 +297,21 @@ public class PluginManagementService : IAssemblyManagementService
|
||||
|
||||
return type;
|
||||
}
|
||||
|
||||
foreach (var ass in AssemblyLoadContext.Default.Assemblies)
|
||||
{
|
||||
if (ass.GetType(typeName, false, false) is not {} type2 || (!includeInterfaces && type2.IsInterface))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
return isByRefType ? type2.MakeByRefType() : type2;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var ass in AssemblyLoadContext.All.SelectMany(alc => alc.Assemblies))
|
||||
foreach (var ass in AssemblyLoadContext.All
|
||||
.Where(alc => alc != AssemblyLoadContext.Default)
|
||||
.SelectMany(alc => alc.Assemblies))
|
||||
{
|
||||
if (ass.GetType(typeName, false, false) is not {} type || (!includeInterfaces && type.IsInterface))
|
||||
{
|
||||
@@ -426,7 +480,7 @@ public class PluginManagementService : IAssemblyManagementService
|
||||
new IAssemblyLoaderService.LoaderInitData(
|
||||
InstanceId: Guid.NewGuid(),
|
||||
contentPackRes.Key.Name,
|
||||
IsReferenceMode: false,
|
||||
IsReferenceMode: contentPackRes.Any(r => r.IsReferenceModeOnly),
|
||||
OwnerPackage: contentPackRes.Key,
|
||||
OnUnload: OnAssemblyLoaderUnloading,
|
||||
OnResolvingManaged: OnAssemblyLoaderResolvingManaged,
|
||||
@@ -465,7 +519,7 @@ public class PluginManagementService : IAssemblyManagementService
|
||||
new IAssemblyLoaderService.LoaderInitData(
|
||||
InstanceId: Guid.NewGuid(),
|
||||
contentPackRes.Key.Name,
|
||||
IsReferenceMode: false,
|
||||
IsReferenceMode: contentPackRes.Any(r => r.IsReferenceModeOnly),
|
||||
OwnerPackage: contentPackRes.Key,
|
||||
OnUnload: OnAssemblyLoaderUnloading,
|
||||
OnResolvingManaged: OnAssemblyLoaderResolvingManaged,
|
||||
@@ -550,35 +604,13 @@ public class PluginManagementService : IAssemblyManagementService
|
||||
|
||||
IEnumerable<MetadataReference> GetMetadataReferences()
|
||||
{
|
||||
#if !DEBUG
|
||||
throw new NotImplementedException($"Needs to use publicized barotrauma assemblies and cache metadata.");
|
||||
#endif
|
||||
var publicizedDir = Path.Combine(Directory.GetCurrentDirectory(), "Publicized");
|
||||
|
||||
string[] publicizedAssemblies =
|
||||
var builder = ImmutableArray.CreateBuilder<MetadataReference>();
|
||||
builder.AddRange(BaseMetadataReferences);
|
||||
foreach (var loaderService in _assemblyLoaders)
|
||||
{
|
||||
#if CLIENT
|
||||
"Barotrauma",
|
||||
#elif SERVER
|
||||
"DedicatedServer",
|
||||
#endif
|
||||
"BarotraumaCore"
|
||||
};
|
||||
|
||||
var publicizedRefs = publicizedAssemblies
|
||||
.Select(name => Path.Combine(publicizedDir, $"{name}.dll"))
|
||||
.Where(File.Exists)
|
||||
.Select(path => MetadataReference.CreateFromFile(path));
|
||||
|
||||
var runtimeRefs = AppDomain.CurrentDomain.GetAssemblies()
|
||||
.Where(ass =>
|
||||
!string.IsNullOrWhiteSpace(ass.Location) &&
|
||||
!publicizedAssemblies.Contains(ass.GetName().Name))
|
||||
.Select(ass => MetadataReference.CreateFromFile(ass.Location));
|
||||
|
||||
return Basic.Reference.Assemblies.Net80.References.All
|
||||
.Union(runtimeRefs)
|
||||
.Union(publicizedRefs);
|
||||
builder.AddRange(loaderService.Value.AssemblyReferences.Where(ar => ar is not null));
|
||||
}
|
||||
return builder.ToImmutable();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user