[Save/Sync] Big If tru Rewrite in progress.

- Removed IProcessors
- Removed old ModConfigService format.
- Converting to ContentPath from absolute paths where possible.
- Added: Microsoft.Toolkit.Diagnostics package.
This commit is contained in:
MapleWheels
2026-01-02 18:02:01 -05:00
committed by Maplewheels
parent 6a6be3caa4
commit 7d39c092c6
12 changed files with 132 additions and 680 deletions
@@ -1,30 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Threading.Tasks;
using System.Xml.Linq;
using Barotrauma.LuaCs.Data;
using FluentResults;
namespace Barotrauma.LuaCs.Services.Processing;
public partial class ModConfigService
{
private partial async Task<Result<IModConfigInfo>> GetModConfigInfoAsync(ContentPackage package, XElement root)
{
var asm = root.GetChildElements("Assembly").ToImmutableArray();
var cfg = root.GetChildElements("Config").ToImmutableArray();
var lua = root.GetChildElements("Lua").ToImmutableArray();
return FluentResults.Result.Ok<IModConfigInfo>(new ModConfigInfo()
{
Package = package,
PackageName = package.Name,
Assemblies = asm.Any() ? GetAssemblies(package, asm) : ImmutableArray<IAssemblyResourceInfo>.Empty,
Configs = cfg.Any() ? GetConfigs(package, cfg) : ImmutableArray<IConfigResourceInfo>.Empty,
ConfigProfiles = cfg.Any() ? GetConfigProfiles(package, cfg) : ImmutableArray<IConfigProfileResourceInfo>.Empty,
LuaScripts = lua.Any() ? GetLuaScripts(package, lua) : ImmutableArray<ILuaScriptResourceInfo>.Empty
});
}
}
+1 -2
View File
@@ -5,15 +5,14 @@
<PackageReference Include="HarmonyX" Version="2.13.0" /> <PackageReference Include="HarmonyX" Version="2.13.0" />
<PackageReference Include="Sigil" Version="5.0.0" /> <PackageReference Include="Sigil" Version="5.0.0" />
<PackageReference Include="LightInject" Version="6.6.4" /> <PackageReference Include="LightInject" Version="6.6.4" />
<PackageReference Include="QuikGraph" Version="2.5.0" />
<PackageReference Include="OneOf" Version="3.0.271" /> <PackageReference Include="OneOf" Version="3.0.271" />
<PackageReference Include="FluentResults" Version="3.16.0" /> <PackageReference Include="FluentResults" Version="3.16.0" />
<PackageReference Include="Basic.Reference.Assemblies.Net60" Version="1.7.9" /> <PackageReference Include="Basic.Reference.Assemblies.Net60" Version="1.7.9" />
<PackageReference Include="ImpromptuInterface " Version="8.0.4" /> <PackageReference Include="ImpromptuInterface " Version="8.0.4" />
<PackageReference Include="Microsoft.Toolkit.Diagnostics" Version="7.1.2"/>
<ProjectReference Include="$(MSBuildThisFileDirectory)..\..\Libraries\moonsharp\MoonSharp.Interpreter\MoonSharp.Interpreter.csproj" /> <ProjectReference Include="$(MSBuildThisFileDirectory)..\..\Libraries\moonsharp\MoonSharp.Interpreter\MoonSharp.Interpreter.csproj" />
<ProjectReference Include="$(MSBuildThisFileDirectory)..\..\Libraries\moonsharp\MoonSharp.VsCodeDebugger\MoonSharp.VsCodeDebugger.csproj" /> <ProjectReference Include="$(MSBuildThisFileDirectory)..\..\Libraries\moonsharp\MoonSharp.VsCodeDebugger\MoonSharp.VsCodeDebugger.csproj" />
</ItemGroup> </ItemGroup>
<!-- <!--
The `Microsoft.CodeAnalysis.CSharp.Scripting` package includes satellites The `Microsoft.CodeAnalysis.CSharp.Scripting` package includes satellites
assemblies, which end up polluting the build folder. assemblies, which end up polluting the build folder.
@@ -40,7 +40,6 @@ namespace Barotrauma
void RegisterServices() void RegisterServices()
{ {
_servicesProvider.RegisterServiceType<IPackageListRetrievalService, PackageListRetrievalService>(ServiceLifetime.Transient); _servicesProvider.RegisterServiceType<IPackageListRetrievalService, PackageListRetrievalService>(ServiceLifetime.Transient);
_servicesProvider.RegisterServiceType<IPackageInfoLookupService, ContentPackageInfoLookup>(ServiceLifetime.Singleton);
_servicesProvider.RegisterServiceType<ILoggerService, LoggerService>(ServiceLifetime.Singleton); _servicesProvider.RegisterServiceType<ILoggerService, LoggerService>(ServiceLifetime.Singleton);
_servicesProvider.RegisterServiceType<PerformanceCounterService, PerformanceCounterService>(ServiceLifetime.Singleton); _servicesProvider.RegisterServiceType<PerformanceCounterService, PerformanceCounterService>(ServiceLifetime.Singleton);
_servicesProvider.RegisterServiceType<IStorageService, StorageService>(ServiceLifetime.Transient); _servicesProvider.RegisterServiceType<IStorageService, StorageService>(ServiceLifetime.Transient);
@@ -55,15 +54,9 @@ namespace Barotrauma
// TODO: INetworkingService // TODO: INetworkingService
// TODO: [Resource Converter/Parser Services] // TODO: [Resource Converter/Parser Services]
// IResourceInfo wrappers and mutators.
_servicesProvider.RegisterServiceType<IProcessorService<IReadOnlyList<IAssemblyResourceInfo>, IAssembliesResourcesInfo>, ResourceInfoArrayPacker>(ServiceLifetime.Transient);
_servicesProvider.RegisterServiceType<IProcessorService<IReadOnlyList<IConfigResourceInfo>, IConfigsResourcesInfo>, ResourceInfoArrayPacker>(ServiceLifetime.Transient);
_servicesProvider.RegisterServiceType<IProcessorService<IReadOnlyList<IConfigProfileResourceInfo>, IConfigProfilesResourcesInfo>, ResourceInfoArrayPacker>(ServiceLifetime.Transient);
_servicesProvider.RegisterServiceType<IProcessorService<IReadOnlyList<ILuaScriptResourceInfo>, ILuaScriptsResourcesInfo>, ResourceInfoArrayPacker>(ServiceLifetime.Transient);
// Loaders and Processors (yes the naming is reversed, oops). // Loaders and Processors (yes the naming is reversed, oops).
_servicesProvider.RegisterServiceType<IConverterService<ContentPackage, IModConfigInfo>, ModConfigService>(ServiceLifetime.Transient); _servicesProvider.RegisterServiceType<IParserService<ContentPackage, IModConfigInfo>, ModConfigService>(ServiceLifetime.Transient);
_servicesProvider.RegisterServiceType<IConverterServiceAsync<ContentPackage, IModConfigInfo>, ModConfigService>(ServiceLifetime.Transient); _servicesProvider.RegisterServiceType<IParserServiceAsync<ContentPackage, IModConfigInfo>, ModConfigService>(ServiceLifetime.Transient);
_servicesProvider.RegisterServiceType<IConfigIOService, ConfigIOService>(ServiceLifetime.Transient); _servicesProvider.RegisterServiceType<IConfigIOService, ConfigIOService>(ServiceLifetime.Transient);
// service config data // service config data
@@ -24,11 +24,11 @@ namespace Barotrauma.LuaCs.Services;
public partial class ConfigService : IConfigService public partial class ConfigService : IConfigService
{ {
//--- Internals //--- Internals
public ConfigService(IConverterServiceAsync<IConfigProfileResourceInfo, IReadOnlyList<IConfigProfileInfo>> configProfileResourceConverter, public ConfigService(IParserServiceAsync<IConfigProfileResourceInfo, IReadOnlyList<IConfigProfileInfo>> configProfileResourceParser,
IConverterServiceAsync<IConfigResourceInfo, IReadOnlyList<IConfigInfo>> configResourceConverter, IEventService eventService, System.Lazy<IStorageService> storageService) IParserServiceAsync<IConfigResourceInfo, IReadOnlyList<IConfigInfo>> configResourceParser, IEventService eventService, System.Lazy<IStorageService> storageService)
{ {
_configProfileResourceConverter = configProfileResourceConverter; _configProfileResourceParser = configProfileResourceParser;
_configResourceConverter = configResourceConverter; _configResourceParser = configResourceParser;
_eventService = eventService; _eventService = eventService;
_storageService = storageService; _storageService = storageService;
this._base = this; this._base = this;
@@ -47,8 +47,8 @@ public partial class ConfigService : IConfigService
private readonly AsyncReaderWriterLock _disposeOpsLock = new(); private readonly AsyncReaderWriterLock _disposeOpsLock = new();
// extern services // extern services
private readonly IConverterServiceAsync<IConfigResourceInfo, IReadOnlyList<IConfigInfo>> _configResourceConverter; private readonly IParserServiceAsync<IConfigResourceInfo, IReadOnlyList<IConfigInfo>> _configResourceParser;
private readonly IConverterServiceAsync<IConfigProfileResourceInfo, IReadOnlyList<IConfigProfileInfo>> _configProfileResourceConverter; private readonly IParserServiceAsync<IConfigProfileResourceInfo, IReadOnlyList<IConfigProfileInfo>> _configProfileResourceParser;
private readonly IEventService _eventService; private readonly IEventService _eventService;
private readonly System.Lazy<IStorageService> _storageService; private readonly System.Lazy<IStorageService> _storageService;
@@ -318,7 +318,7 @@ public partial class ConfigService : IConfigService
if (configResources.IsDefaultOrEmpty) if (configResources.IsDefaultOrEmpty)
return FluentResults.Result.Fail($"{nameof(LoadConfigsAsync)}: Array is empty."); return FluentResults.Result.Fail($"{nameof(LoadConfigsAsync)}: Array is empty.");
var results = await _configResourceConverter.TryParseResourcesAsync(configResources); var results = await _configResourceParser.TryParseResourcesAsync(configResources);
var ret = new FluentResults.Result(); var ret = new FluentResults.Result();
foreach (var result in results) foreach (var result in results)
@@ -365,7 +365,7 @@ public partial class ConfigService : IConfigService
if (configProfileResources.IsDefaultOrEmpty) if (configProfileResources.IsDefaultOrEmpty)
return FluentResults.Result.Fail($"{nameof(LoadConfigsProfilesAsync)}: Array is empty."); return FluentResults.Result.Fail($"{nameof(LoadConfigsProfilesAsync)}: Array is empty.");
var results = await _configProfileResourceConverter.TryParseResourcesAsync(configProfileResources); var results = await _configProfileResourceParser.TryParseResourcesAsync(configProfileResources);
var ret = new FluentResults.Result(); var ret = new FluentResults.Result();
foreach (var result in results) foreach (var result in results)
@@ -46,7 +46,7 @@ public class ConfigIOService : IConfigIOService
try try
{ {
var infos = await _storageService.LoadPackageXmlFilesAsync(src.OwnerPackage, src.FilePaths); var infos = await _storageService.LoadPackageXmlFilesAsync(src.OwnerPackage, [..src.FilePaths.Select(fp => fp.FullPath)]);
if (infos.IsDefaultOrEmpty) if (infos.IsDefaultOrEmpty)
return FluentResults.Result.Fail($"{nameof(TryParseResourceAsync)}: No resources found."); return FluentResults.Result.Fail($"{nameof(TryParseResourceAsync)}: No resources found.");
@@ -7,8 +7,8 @@ using Barotrauma.LuaCs.Services.Processing;
namespace Barotrauma.LuaCs.Services.Processing; namespace Barotrauma.LuaCs.Services.Processing;
public interface IConfigIOService : IReusableService, public interface IConfigIOService : IReusableService,
IConverterServiceAsync<IConfigResourceInfo, IReadOnlyList<IConfigInfo>>, IParserServiceAsync<IConfigResourceInfo, IReadOnlyList<IConfigInfo>>,
IConverterServiceAsync<IConfigProfileResourceInfo, IReadOnlyList<IConfigProfileInfo>> IParserServiceAsync<IConfigProfileResourceInfo, IReadOnlyList<IConfigProfileInfo>>
{ {
Task<FluentResults.Result> SaveConfigDataLocal(ContentPackage package, string configName, XElement serializedValue); Task<FluentResults.Result> SaveConfigDataLocal(ContentPackage package, string configName, XElement serializedValue);
Task<FluentResults.Result<OneOf.OneOf<string, XElement>>> LoadConfigDataFromLocal(ContentPackage package, string configName); Task<FluentResults.Result<OneOf.OneOf<string, XElement>>> LoadConfigDataFromLocal(ContentPackage package, string configName);
@@ -7,24 +7,14 @@ using FluentResults;
namespace Barotrauma.LuaCs.Services.Processing; namespace Barotrauma.LuaCs.Services.Processing;
public interface IConverterService<in TSrc, TOut> : IService public interface IParserService<in TSrc, TOut> : IService
{ {
Result<TOut> TryParseResource(TSrc src); Result<TOut> TryParseResource(TSrc src);
ImmutableArray<Result<TOut>> TryParseResources(IEnumerable<TSrc> sources); ImmutableArray<Result<TOut>> TryParseResources(IEnumerable<TSrc> sources);
} }
public interface IConverterServiceAsync<in TSrc, TOut> : IService public interface IParserServiceAsync<in TSrc, TOut> : IService
{ {
Task<Result<TOut>> TryParseResourceAsync(TSrc src); Task<Result<TOut>> TryParseResourceAsync(TSrc src);
Task<ImmutableArray<Result<TOut>>> TryParseResourcesAsync(IEnumerable<TSrc> sources); Task<ImmutableArray<Result<TOut>>> TryParseResourcesAsync(IEnumerable<TSrc> sources);
} }
public interface IProcessorService<in TSrc, TOut> : IService
{
TOut Process(TSrc src);
}
public interface IProcessorServiceAsync<in TSrc, TOut> : IService
{
Task<TOut> ProcessAsync(TSrc src);
}
@@ -12,545 +12,81 @@ using FluentResults;
namespace Barotrauma.LuaCs.Services.Processing; namespace Barotrauma.LuaCs.Services.Processing;
public partial class ModConfigService : IConverterServiceAsync<ContentPackage, IModConfigInfo>, IConverterService<ContentPackage, IModConfigInfo> public sealed class ModConfigService : IModConfigService
{ {
private readonly IStorageService _storageService; private IStorageService _storageService;
private readonly Lazy<IPackageManagementService> _packageManagementService; private IParserServiceAsync<XElement, IAssemblyResourceInfo> _assemblyParserService;
private int _isDisposed; private IParserServiceAsync<XElement, ILuaScriptResourceInfo> _luaScriptParserService;
private IParserServiceAsync<XElement, IConfigResourceInfo> _configParserService;
private IParserServiceAsync<XElement, IConfigProfileResourceInfo> _configProfileParserService;
private const string ModConfigFileName = "ModConfig.xml"; public ModConfigService(IStorageService storageService,
private const string ModConfigRootName = "ModConfig"; IParserServiceAsync<XElement, IAssemblyResourceInfo> assemblyParserService,
IParserServiceAsync<XElement, ILuaScriptResourceInfo> luaScriptParserService,
public ModConfigService(IStorageService storageService, Lazy<IPackageManagementService> pms) IParserServiceAsync<XElement, IConfigResourceInfo> configParserService,
IParserServiceAsync<XElement, IConfigProfileResourceInfo> configProfileParserService)
{ {
_storageService = storageService; _storageService = storageService;
_packageManagementService = pms; _assemblyParserService = assemblyParserService;
_luaScriptParserService = luaScriptParserService;
_configParserService = configParserService;
_configProfileParserService = configProfileParserService;
} }
#region Disposal
public void Dispose() public void Dispose()
{ {
throw new System.NotImplementedException(); throw new NotImplementedException();
} }
private int _isDisposed = 0;
public bool IsDisposed public bool IsDisposed
{ {
get => ModUtils.Threading.GetBool(ref _isDisposed); get => ModUtils.Threading.GetBool(ref _isDisposed);
private set => ModUtils.Threading.SetBool(ref _isDisposed, value); protected set => ModUtils.Threading.SetBool(ref _isDisposed, value);
} }
public async Task<Result<IModConfigInfo>> TryParseResourceAsync(ContentPackage src) #endregion
{
((IService)this).CheckDisposed();
// validate package public async Task<Result<IModConfigInfo>> CreateConfigAsync(ContentPackage src)
{
if (src is null) if (src is null)
return FluentResults.Result.Fail<IModConfigInfo>("ContentPackage is null"); ArgumentNullException.ThrowIfNull($"{nameof(CreateConfigAsync)}: Source is null.");
if (_storageService.DirectoryExists(src.Path) is { } res && (res.IsFailed || !res.Value))
return FluentResults.Result.Fail<IModConfigInfo>($"ContentPackage does not exist or cannot be accessed: {src.Path}");
// find ModConfig.xml or deep scan on fail (legacy) if (await TryGetModConfigXmlAsync(src) is { IsSuccess: true, Value: { } config })
if (await _storageService.LoadPackageXmlAsync(src, ModConfigFileName) is
{ IsSuccess: true, Value: var modConfigXml }
&& modConfigXml.Root is { Name.LocalName: ModConfigRootName } root)
{ {
return await GetModConfigInfoAsync(src, root); return await CreateFromConfigXmlAsync(config);
} }
// legacy mode return await CreateFromLegacyAsync(src);
try
{
// we only supported assemblies and lua scripts
var asm = GetAssembliesLegacy(src);
var lua = GetLuaScriptsLegacy(src);
return new ModConfigInfo()
{
Assemblies = asm,
LuaScripts = lua,
Configs = ImmutableArray<IConfigResourceInfo>.Empty,
ConfigProfiles = ImmutableArray<IConfigProfileResourceInfo>.Empty,
Package = src,
PackageName = src.Name
};
}
catch (Exception e)
{
return FluentResults.Result.Fail<IModConfigInfo>($"Unable to parse legacy content package: {src.Name}: {src.Path}");
}
} }
private partial Task<Result<IModConfigInfo>> GetModConfigInfoAsync(ContentPackage package, XElement root); public async Task<ImmutableArray<(ContentPackage Source, Result<IModConfigInfo> Config)>> CreateConfigsAsync(ImmutableArray<ContentPackage> src)
private ImmutableArray<IAssemblyResourceInfo> GetAssemblies(ContentPackage src, IEnumerable<XElement> elements)
{ {
var builder = ImmutableArray.CreateBuilder<IAssemblyResourceInfo>(); var builder = ImmutableArray.CreateBuilder<(ContentPackage Source, Result<IModConfigInfo> Config)>();
var elementsList = elements.ToImmutableArray();
if (GetFilesList(src, elementsList, "Assembly", "*.dll") foreach (var package in src)
is not { IsSuccess: true, Value: { } xmlFiles })
return ImmutableArray<IAssemblyResourceInfo>.Empty;
foreach (var file in xmlFiles)
{ {
// get platform, culture and target architecture builder.Add((package, await CreateConfigAsync(package)));
var info = GetElementsAttributesData(file.Item1, file.Item2.First());
builder.Add(new AssemblyResourceInfo()
{
Optional = info.IsOptional,
FilePaths = file.Item2,
InternalName = info.Name,
LoadPriority = info.LoadPriority,
OwnerPackage = src,
SupportedPlatforms = info.SupportedPlatforms,
SupportedTargets = info.SupportedTargets,
FriendlyName = file.Item1.GetAttributeString("Name", info.Name),
IsScript = false
});
} }
if (GetFilesList(src, elementsList, "Assembly", "*.cs") return builder.ToImmutable();
is not { IsSuccess: true, Value: { } xmlFiles2 })
return ImmutableArray<IAssemblyResourceInfo>.Empty;
foreach (var file in xmlFiles2)
{
// get platform, culture and target architecture
var info = GetElementsAttributesData(file.Item1, file.Item2.First());
builder.Add(new AssemblyResourceInfo()
{
Optional = info.IsOptional,
FilePaths = file.Item2,
InternalName = info.Name,
LoadPriority = info.LoadPriority,
OwnerPackage = src,
SupportedPlatforms = info.SupportedPlatforms,
SupportedTargets = info.SupportedTargets,
FriendlyName = file.Item1.GetAttributeString("Name", info.Name),
IsScript = true
});
} }
return builder.Count > 0 //--- Helpers
? builder.ToImmutable() private async Task<Result<XElement>> TryGetModConfigXmlAsync(ContentPackage src)
: ImmutableArray<IAssemblyResourceInfo>.Empty; {
} }
private ImmutableArray<IConfigResourceInfo> GetConfigs(ContentPackage src, IEnumerable<XElement> elements) private async Task<Result<IModConfigInfo>> CreateFromConfigXmlAsync(XElement src)
{ {
var builder = ImmutableArray.CreateBuilder<IConfigResourceInfo>(); throw new NotImplementedException();
if (GetXmlFilesList(src, elements, "Config")
is not { IsSuccess: true, Value: { } xmlFiles })
return ImmutableArray<IConfigResourceInfo>.Empty;
foreach (var file in xmlFiles)
{
// get platform, culture and target architecture
var info = GetElementsAttributesData(file.Item1, file.Item2.First());
builder.Add(new ConfigResourceInfo()
{
Optional = info.IsOptional,
FilePaths = file.Item2,
InternalName = info.Name,
LoadPriority = info.LoadPriority,
OwnerPackage = src,
SupportedPlatforms = info.SupportedPlatforms,
SupportedTargets = info.SupportedTargets
});
} }
return builder.Count > 0 private async Task<Result<IModConfigInfo>> CreateFromLegacyAsync(ContentPackage src)
? builder.ToImmutable() {
: ImmutableArray<IConfigResourceInfo>.Empty; throw new NotImplementedException();
} }
private ImmutableArray<IConfigProfileResourceInfo> GetConfigProfiles(ContentPackage src, IEnumerable<XElement> elements)
{
var builder = ImmutableArray.CreateBuilder<IConfigProfileResourceInfo>();
if (GetXmlFilesList(src, elements, "Config")
is not { IsSuccess: true, Value: { } xmlFiles })
return ImmutableArray<IConfigProfileResourceInfo>.Empty;
foreach (var file in xmlFiles)
{
// get platform, culture and target architecture
var info = GetElementsAttributesData(file.Item1, file.Item2.First());
builder.Add(new ConfigProfileResourceInfo()
{
Optional = info.IsOptional,
FilePaths = file.Item2,
InternalName = info.Name,
LoadPriority = info.LoadPriority,
OwnerPackage = src,
SupportedPlatforms = info.SupportedPlatforms,
SupportedTargets = info.SupportedTargets
});
}
return builder.Count > 0
? builder.ToImmutable()
: ImmutableArray<IConfigProfileResourceInfo>.Empty;
}
private ImmutableArray<ILuaScriptResourceInfo> GetLuaScripts(ContentPackage src, IEnumerable<XElement> elements)
{
var builder = ImmutableArray.CreateBuilder<ILuaScriptResourceInfo>();
if (GetXmlFilesList(src, elements, "Config")
is not { IsSuccess: true, Value: { } xmlFiles })
return ImmutableArray<ILuaScriptResourceInfo>.Empty;
foreach (var file in xmlFiles)
{
// get platform, culture and target architecture
var info = GetElementsAttributesData(file.Item1, file.Item2.First());
builder.Add(new LuaScriptsResourceInfo()
{
Optional = info.IsOptional,
FilePaths = file.Item2,
InternalName = info.Name,
LoadPriority = info.LoadPriority,
OwnerPackage = src,
SupportedPlatforms = info.SupportedPlatforms,
SupportedTargets = info.SupportedTargets,
IsAutorun = file.Item1.GetAttributeBool("RunFile", true)
});
}
return builder.Count > 0
? builder.ToImmutable()
: ImmutableArray<ILuaScriptResourceInfo>.Empty;
}
private Result<ImmutableArray<(XElement, ImmutableArray<string>)>> GetXmlFilesList(ContentPackage src,
IEnumerable<XElement> elements, string elementNameCheck) =>
GetFilesList(src, elements, elementNameCheck, "*.xml");
private Result<ImmutableArray<(XElement, ImmutableArray<string>)>> GetFilesList(ContentPackage src,
IEnumerable<XElement> elements, string elementNameCheck, string filter)
{
var builder = ImmutableArray.CreateBuilder<(XElement, ImmutableArray<string>)>();
if (elementNameCheck.IsNullOrWhiteSpace())
throw new ArgumentNullException($"{nameof(GetXmlFilesList)}: The element check is null.");
foreach (var element in elements)
{
if (element.Name.LocalName != elementNameCheck)
throw new ArgumentException("Element is not a Localization element");
if (element.GetAttributeString("Folder", string.Empty) is { } str
&& !string.IsNullOrWhiteSpace(str))
{
if (_storageService.FindFilesInPackage(src, str, filter, true)
is not { IsSuccess: true, Value: var fpList } || !fpList.Any())
{
continue;
}
foreach (var fileP in fpList)
builder.Add((element, fpList.ToImmutableArray()));
}
else if (element.GetAttributeString("File", string.Empty) is { } fileStr
&& !string.IsNullOrWhiteSpace(fileStr)
&& _storageService.GetAbsFromPackage(src, fileStr) is { IsSuccess: true, Value: var fp }
&& _storageService.FileExists(fp) is { IsSuccess: true, Value: true })
{
builder.Add((element, new [] { fileStr }.ToImmutableArray()));
}
}
return builder.Count > 0
? FluentResults.Result.Ok(builder.ToImmutable())
: FluentResults.Result.Fail($"No files found");
}
private ResourceAdditionalInfo GetElementsAttributesData(XElement element, string localPath)
{
return new ResourceAdditionalInfo(
element.GetAttributeString("Name", localPath),
GetSupportedPlatforms(element.GetAttributeString("Platform", "any")),
GetSupportedTargets(element.GetAttributeString("Target", "any")),
GetSupportedCultures(element),
element.GetAttributeBool("Optional", false),
element.GetAttributeInt("Priority", 0));
Platform GetSupportedPlatforms(string platformName) => platformName.ToLowerInvariant().Trim() switch
{
"windows" => Platform.Windows,
"linux" => Platform.Linux,
"osx" => Platform.OSX,
_ => Platform.Windows | Platform.Linux | Platform.OSX
};
Target GetSupportedTargets(string targetName) => targetName.ToLowerInvariant().Trim() switch
{
"client" => Target.Client,
"server" => Target.Server,
_ => Target.Client | Target.Server,
};
ImmutableArray<CultureInfo> GetSupportedCultures(XElement element)
{
var culture = element.GetAttributeString("Culture", string.Empty);
if (string.IsNullOrWhiteSpace(culture))
return new[] { CultureInfo.InvariantCulture }.ToImmutableArray();
var builder = ImmutableArray.CreateBuilder<CultureInfo>();
var arr = culture.Split(',');
if (arr.Length == 0)
return new[] { CultureInfo.InvariantCulture }.ToImmutableArray();
foreach (var culstr in arr)
{
if (string.IsNullOrWhiteSpace(culstr))
continue;
try
{
builder.Add(
culstr.ToLowerInvariant().Trim() == "default"
? CultureInfo.InvariantCulture
: CultureInfo.GetCultureInfo(culstr));
}
catch (CultureNotFoundException e)
{
// This is the case if a culture is specified by the package that is not supported by the OS/.NET ENV.
// We ignore it since we can never use it.
continue;
}
}
return builder.Count > 0
? builder.ToImmutable()
: new[] { CultureInfo.InvariantCulture }.ToImmutableArray();
}
}
private ImmutableArray<IAssemblyResourceInfo> GetAssembliesLegacy(ContentPackage src)
{
var builder = ImmutableArray.CreateBuilder<IAssemblyResourceInfo>();
// server, linux
if (_storageService.FindFilesInPackage(src, "bin/Server/Linux", "*.dll", true)
is { IsSuccess: true, Value: { IsDefaultOrEmpty: false} filesSrvLin})
{
builder.Add(new AssemblyResourceInfo()
{
FilePaths = filesSrvLin,
FriendlyName = "AssembliesServerLinux",
InternalName = "AssembliesServerLinux",
IsScript = false,
LoadPriority = 1,
Optional = false,
OwnerPackage = src,
SupportedPlatforms = Platform.Linux,
SupportedTargets = Target.Server
});
}
// server, osx
if (_storageService.FindFilesInPackage(src, "bin/Server/OSX", "*.dll", true)
is { IsSuccess: true, Value: { IsDefaultOrEmpty: false} filesSrvOsx})
{
builder.Add(new AssemblyResourceInfo()
{
FilePaths = filesSrvOsx,
FriendlyName = "AssembliesServerOSX",
InternalName = "AssembliesServerOSX",
IsScript = false,
LoadPriority = 1,
Optional = false,
OwnerPackage = src,
SupportedPlatforms = Platform.OSX,
SupportedTargets = Target.Server
});
}
// server, osx
if (_storageService.FindFilesInPackage(src, "bin/Server/Windows", "*.dll", true)
is { IsSuccess: true, Value: { IsDefaultOrEmpty: false} filesSrvWin})
{
builder.Add(new AssemblyResourceInfo()
{
FilePaths = filesSrvWin,
FriendlyName = "AssembliesServerWin",
InternalName = "AssembliesServerWin",
IsScript = false,
LoadPriority = 1,
Optional = false,
OwnerPackage = src,
SupportedPlatforms = Platform.Windows,
SupportedTargets = Target.Server
});
}
// client, linux
if (_storageService.FindFilesInPackage(src, "bin/Client/Linux", "*.dll", true)
is { IsSuccess: true, Value: { IsDefaultOrEmpty: false} filesCliLin})
{
builder.Add(new AssemblyResourceInfo()
{
FilePaths = filesCliLin,
FriendlyName = "AssembliesClientLinux",
InternalName = "AssembliesClientLinux",
IsScript = false,
LoadPriority = 1,
Optional = false,
OwnerPackage = src,
SupportedPlatforms = Platform.Linux,
SupportedTargets = Target.Client
});
}
// server, osx
if (_storageService.FindFilesInPackage(src, "bin/Client/OSX", "*.dll", true)
is { IsSuccess: true, Value: { IsDefaultOrEmpty: false} filesCliOsx})
{
builder.Add(new AssemblyResourceInfo()
{
FilePaths = filesCliOsx,
FriendlyName = "AssembliesClientOSX",
InternalName = "AssembliesClientOSX",
IsScript = false,
LoadPriority = 1,
Optional = false,
OwnerPackage = src,
SupportedPlatforms = Platform.OSX,
SupportedTargets = Target.Client
});
}
// server, osx
if (_storageService.FindFilesInPackage(src, "bin/Client/Windows", "*.dll", true)
is { IsSuccess: true, Value: { IsDefaultOrEmpty: false} filesCliWin})
{
builder.Add(new AssemblyResourceInfo()
{
FilePaths = filesCliWin,
FriendlyName = "AssembliesClientWin",
InternalName = "AssembliesClientWin",
IsScript = false,
LoadPriority = 1,
Optional = false,
OwnerPackage = src,
SupportedPlatforms = Platform.Windows,
SupportedTargets = Target.Client
});
}
var sharedCsBuilder = ImmutableArray.CreateBuilder<string>();
if (_storageService.FindFilesInPackage(src, "CSharp/Shared", "*.cs", true)
is { IsSuccess: true, Value: { IsDefaultOrEmpty: false } files })
{
sharedCsBuilder.AddRange<string>(files);
}
var filesCssShared = sharedCsBuilder.MoveToImmutable();
var sharedFound = !filesCssShared.IsDefaultOrEmpty;
// source files legacy: server
if (_storageService.FindFilesInPackage(src, "CSharp/Server", "*.cs", true)
is { IsSuccess: true, Value: { IsDefaultOrEmpty: false} filesCssServer})
{
builder.Add(new AssemblyResourceInfo()
{
FilePaths = sharedFound ? filesCssServer.Concat(filesCssShared).ToImmutableArray() : filesCssServer,
FriendlyName = "CssServer",
InternalName = "CssServer",
IsScript = true,
LoadPriority = 1,
Optional = false,
OwnerPackage = src,
SupportedPlatforms = Platform.Linux | Platform.OSX | Platform.Windows,
SupportedTargets = Target.Server
});
}
// source files legacy: client
if (_storageService.FindFilesInPackage(src, "CSharp/Client", "*.cs", true)
is { IsSuccess: true, Value: { IsDefaultOrEmpty: false} filesCssClient})
{
builder.Add(new AssemblyResourceInfo()
{
FilePaths = sharedFound ? filesCssClient.Concat(filesCssShared).ToImmutableArray() : filesCssClient,
FriendlyName = "CssClient",
InternalName = "CssClient",
IsScript = true,
LoadPriority = 1,
Optional = false,
OwnerPackage = src,
SupportedPlatforms = Platform.Linux | Platform.OSX | Platform.Windows,
SupportedTargets = Target.Client
});
}
return builder.MoveToImmutable();
}
private ImmutableArray<ILuaScriptResourceInfo> GetLuaScriptsLegacy(ContentPackage src)
{
var builder = ImmutableArray.CreateBuilder<ILuaScriptResourceInfo>();
if (_storageService.FindFilesInPackage(src, "Lua", "*.lua", true)
is { IsSuccess: true, Value: { IsDefaultOrEmpty: false } fileAll })
{
builder.Add(new LuaScriptsResourceInfo()
{
FilePaths = fileAll.Where(path => !path.Contains("Autorun")).ToImmutableArray(),
InternalName = "LuaScriptsNormal",
Optional = false,
IsAutorun = false,
OwnerPackage = src,
SupportedPlatforms = Platform.Linux | Platform.OSX | Platform.Windows,
SupportedTargets = Target.Client | Target.Server
});
builder.Add(new LuaScriptsResourceInfo()
{
FilePaths = fileAll.Where(path => path.Contains("Autorun")).ToImmutableArray(),
InternalName = "LuaScriptsAutorun",
Optional = false,
IsAutorun = true,
OwnerPackage = src,
SupportedPlatforms = Platform.Linux | Platform.OSX | Platform.Windows,
SupportedTargets = Target.Client | Target.Server
});
}
return builder.MoveToImmutable();
}
public async Task<ImmutableArray<Result<IModConfigInfo>>> TryParseResourcesAsync(IEnumerable<ContentPackage> sources)
{
((IService)this).CheckDisposed();
var srcs = sources.ToImmutableArray();
var results = new AsyncLocal<ConcurrentQueue<Result<IModConfigInfo>>>();
await srcs.ParallelForEachAsync(async pkg =>
{
try
{
results.Value.Enqueue(await TryParseResourceAsync(pkg));
}
catch (Exception e)
{
// this should never happen but this is to stop partial execution exit.
results.Value.Enqueue(
FluentResults.Result.Fail<IModConfigInfo>($"Failed to parse package {pkg?.Name}: {e.Message}"));
}
});
return results.Value.ToImmutableArray();
}
public Result<IModConfigInfo> TryParseResource(ContentPackage src) =>
TryParseResourceAsync(src).GetAwaiter().GetResult();
public ImmutableArray<Result<IModConfigInfo>> TryParseResources(IEnumerable<ContentPackage> sources) =>
TryParseResourcesAsync(sources.ToImmutableArray()).GetAwaiter().GetResult();
private record ResourceAdditionalInfo(
string Name,
Platform SupportedPlatforms,
Target SupportedTargets,
ImmutableArray<CultureInfo> SupportedCultures,
bool IsOptional,
int LoadPriority);
} }
@@ -1,47 +0,0 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Barotrauma.LuaCs.Data;
namespace Barotrauma.LuaCs.Services.Processing;
public partial class ResourceInfoArrayPacker :
IProcessorService<IReadOnlyList<IAssemblyResourceInfo>, IAssembliesResourcesInfo>,
IProcessorService<IReadOnlyList<IConfigResourceInfo>, IConfigsResourcesInfo>,
IProcessorService<IReadOnlyList<IConfigProfileResourceInfo>, IConfigProfilesResourcesInfo>,
IProcessorService<IReadOnlyList<ILuaScriptResourceInfo>, ILuaScriptsResourcesInfo>
{
private bool _isDisposed;
public IAssembliesResourcesInfo Process(IReadOnlyList<IAssemblyResourceInfo> src)
{
return new AssemblyResourcesInfo(src.ToImmutableArray());
}
public IConfigsResourcesInfo Process(IReadOnlyList<IConfigResourceInfo> src)
{
return new ConfigResourcesInfo(src.ToImmutableArray());
}
public IConfigProfilesResourcesInfo Process(IReadOnlyList<IConfigProfileResourceInfo> src)
{
return new ConfigProfilesResourcesInfo(src.ToImmutableArray());
}
public ILuaScriptsResourcesInfo Process(IReadOnlyList<ILuaScriptResourceInfo> src)
{
return new LuaScriptsResourcesInfo(src.ToImmutableArray());
}
public void Dispose()
{
// Stateless class
GC.SuppressFinalize(this);
IsDisposed = true;
}
public bool IsDisposed
{
get => _isDisposed;
set => _isDisposed = value;
}
}
@@ -15,6 +15,7 @@ using Barotrauma.LuaCs.Data;
using Barotrauma.Steam; using Barotrauma.Steam;
using FluentResults; using FluentResults;
using FluentResults.LuaCs; using FluentResults.LuaCs;
using Microsoft.Toolkit.Diagnostics;
using Error = FluentResults.Error; using Error = FluentResults.Error;
using Path = Barotrauma.IO.Path; using Path = Barotrauma.IO.Path;
@@ -98,49 +99,49 @@ public class StorageService : IStorageService
} }
public virtual FluentResults.Result<XDocument> LoadLocalXml(ContentPackage package, string localFilePath) => public virtual FluentResults.Result<XDocument> LoadLocalXml(ContentPackage package, string localFilePath) =>
GetAbsFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null } GetAbsoluePathFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null }
? TryLoadXml(r.Value) : r.ToResult(); ? TryLoadXml(r.Value) : r.ToResult();
public virtual FluentResults.Result<byte[]> LoadLocalBinary(ContentPackage package, string localFilePath) => public virtual FluentResults.Result<byte[]> LoadLocalBinary(ContentPackage package, string localFilePath) =>
GetAbsFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null } GetAbsoluePathFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null }
? TryLoadBinary(r.Value) : r.ToResult(); ? TryLoadBinary(r.Value) : r.ToResult();
public virtual FluentResults.Result<string> LoadLocalText(ContentPackage package, string localFilePath) => public virtual FluentResults.Result<string> LoadLocalText(ContentPackage package, string localFilePath) =>
GetAbsFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null } GetAbsoluePathFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null }
? TryLoadText(r.Value) : r.ToResult(); ? TryLoadText(r.Value) : r.ToResult();
public virtual FluentResults.Result SaveLocalXml(ContentPackage package, string localFilePath, XDocument document) => public virtual FluentResults.Result SaveLocalXml(ContentPackage package, string localFilePath, XDocument document) =>
GetAbsFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null } GetAbsoluePathFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null }
? TrySaveXml(r.Value, document) : r.ToResult(); ? TrySaveXml(r.Value, document) : r.ToResult();
public virtual FluentResults.Result SaveLocalBinary(ContentPackage package, string localFilePath, in byte[] bytes) => public virtual FluentResults.Result SaveLocalBinary(ContentPackage package, string localFilePath, in byte[] bytes) =>
GetAbsFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null } GetAbsoluePathFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null }
? TrySaveBinary(r.Value, bytes) : r.ToResult(); ? TrySaveBinary(r.Value, bytes) : r.ToResult();
public virtual FluentResults.Result SaveLocalText(ContentPackage package, string localFilePath, in string text) => public virtual FluentResults.Result SaveLocalText(ContentPackage package, string localFilePath, in string text) =>
GetAbsFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null } GetAbsoluePathFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null }
? TrySaveText(r.Value, text) : r.ToResult(); ? TrySaveText(r.Value, text) : r.ToResult();
public virtual async Task<FluentResults.Result<XDocument>> LoadLocalXmlAsync(ContentPackage package, string localFilePath) => public virtual async Task<FluentResults.Result<XDocument>> LoadLocalXmlAsync(ContentPackage package, string localFilePath) =>
GetAbsFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null } GetAbsoluePathFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null }
? await TryLoadXmlAsync(r.Value) : r.ToResult(); ? await TryLoadXmlAsync(r.Value) : r.ToResult();
public virtual async Task<FluentResults.Result<byte[]>> LoadLocalBinaryAsync(ContentPackage package, string localFilePath) => public virtual async Task<FluentResults.Result<byte[]>> LoadLocalBinaryAsync(ContentPackage package, string localFilePath) =>
GetAbsFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null } GetAbsoluePathFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null }
? await TryLoadBinaryAsync(r.Value) : r.ToResult(); ? await TryLoadBinaryAsync(r.Value) : r.ToResult();
public virtual async Task<FluentResults.Result<string>> LoadLocalTextAsync(ContentPackage package, string localFilePath) => public virtual async Task<FluentResults.Result<string>> LoadLocalTextAsync(ContentPackage package, string localFilePath) =>
GetAbsFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null } GetAbsoluePathFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null }
? await TryLoadTextAsync(r.Value) : r.ToResult(); ? await TryLoadTextAsync(r.Value) : r.ToResult();
public virtual async Task<FluentResults.Result> SaveLocalXmlAsync(ContentPackage package, string localFilePath, XDocument document) => public virtual async Task<FluentResults.Result> SaveLocalXmlAsync(ContentPackage package, string localFilePath, XDocument document) =>
GetAbsFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null } GetAbsoluePathFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null }
? await TrySaveXmlAsync(r.Value, document) : r.ToResult(); ? await TrySaveXmlAsync(r.Value, document) : r.ToResult();
public virtual async Task<FluentResults.Result> SaveLocalBinaryAsync(ContentPackage package, string localFilePath, byte[] bytes) => public virtual async Task<FluentResults.Result> SaveLocalBinaryAsync(ContentPackage package, string localFilePath, byte[] bytes) =>
GetAbsFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null } GetAbsoluePathFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null }
? await TrySaveBinaryAsync(r.Value, bytes) : r.ToResult(); ? await TrySaveBinaryAsync(r.Value, bytes) : r.ToResult();
public virtual async Task<FluentResults.Result> SaveLocalTextAsync(ContentPackage package, string localFilePath, string text) => public virtual async Task<FluentResults.Result> SaveLocalTextAsync(ContentPackage package, string localFilePath, string text) =>
GetAbsFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null } GetAbsoluePathFromLocal(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null }
? await TrySaveTextAsync(r.Value, text) : r.ToResult(); ? await TrySaveTextAsync(r.Value, text) : r.ToResult();
public virtual FluentResults.Result<XDocument> LoadPackageXml(ContentPackage package, string localFilePath) => public virtual FluentResults.Result<XDocument> LoadPackageXml(ContentPackage package, string localFilePath) =>
GetAbsFromPackage(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null } GetAbsoluePathFromPackage(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null }
? TryLoadXml(r.Value) : r.ToResult(); ? TryLoadXml(r.Value) : r.ToResult();
public virtual FluentResults.Result<byte[]> LoadPackageBinary(ContentPackage package, string localFilePath) => public virtual FluentResults.Result<byte[]> LoadPackageBinary(ContentPackage package, string localFilePath) =>
GetAbsFromPackage(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null } GetAbsoluePathFromPackage(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null }
? TryLoadBinary(r.Value) : r.ToResult(); ? TryLoadBinary(r.Value) : r.ToResult();
public virtual FluentResults.Result<string> LoadPackageText(ContentPackage package, string localFilePath) => public virtual FluentResults.Result<string> LoadPackageText(ContentPackage package, string localFilePath) =>
GetAbsFromPackage(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null } GetAbsoluePathFromPackage(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null }
? TryLoadText(r.Value) : r.ToResult(); ? TryLoadText(r.Value) : r.ToResult();
@@ -181,7 +182,7 @@ public class StorageService : IStorageService
public virtual FluentResults.Result<ImmutableArray<string>> FindFilesInPackage(ContentPackage package, string localSubfolder, string regexFilter, bool searchRecursively) public virtual FluentResults.Result<ImmutableArray<string>> FindFilesInPackage(ContentPackage package, string localSubfolder, string regexFilter, bool searchRecursively)
{ {
((IService)this).CheckDisposed(); ((IService)this).CheckDisposed();
var r = GetAbsFromPackage(package, localSubfolder); var r = GetAbsoluePathFromPackage(package, localSubfolder);
if (r is { IsFailed: true }) if (r is { IsFailed: true })
return r.ToResult(); return r.ToResult();
var builder = ImmutableArray.CreateBuilder<(string, FluentResults.Result<ImmutableArray<string>>)>(); var builder = ImmutableArray.CreateBuilder<(string, FluentResults.Result<ImmutableArray<string>>)>();
@@ -192,15 +193,15 @@ public class StorageService : IStorageService
} }
public virtual async Task<FluentResults.Result<XDocument>> LoadPackageXmlAsync(ContentPackage package, string localFilePath) => public virtual async Task<FluentResults.Result<XDocument>> LoadPackageXmlAsync(ContentPackage package, string localFilePath) =>
GetAbsFromPackage(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null } GetAbsoluePathFromPackage(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null }
? await TryLoadXmlAsync(r.Value) : r.ToResult(); ? await TryLoadXmlAsync(r.Value) : r.ToResult();
public virtual async Task<FluentResults.Result<byte[]>> LoadPackageBinaryAsync(ContentPackage package, string localFilePath) => public virtual async Task<FluentResults.Result<byte[]>> LoadPackageBinaryAsync(ContentPackage package, string localFilePath) =>
GetAbsFromPackage(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null } GetAbsoluePathFromPackage(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null }
? await TryLoadBinaryAsync(r.Value) : r.ToResult(); ? await TryLoadBinaryAsync(r.Value) : r.ToResult();
public virtual async Task<FluentResults.Result<string>> LoadPackageTextAsync(ContentPackage package, string localFilePath) => public virtual async Task<FluentResults.Result<string>> LoadPackageTextAsync(ContentPackage package, string localFilePath) =>
GetAbsFromPackage(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null } GetAbsoluePathFromPackage(package, localFilePath) is var r && r is { IsSuccess: true, Value: not null }
? await TryLoadTextAsync(r.Value) : r.ToResult(); ? await TryLoadTextAsync(r.Value) : r.ToResult();
public virtual async Task<ImmutableArray<(string, FluentResults.Result<XDocument>)>> LoadPackageXmlFilesAsync(ContentPackage package, ImmutableArray<string> localFilePaths) public virtual async Task<ImmutableArray<(string, FluentResults.Result<XDocument>)>> LoadPackageXmlFilesAsync(ContentPackage package, ImmutableArray<string> localFilePaths)
@@ -529,7 +530,7 @@ public class StorageService : IStorageService
.WithMetadata(MetadataType.ExceptionObject, this) .WithMetadata(MetadataType.ExceptionObject, this)
.WithMetadata(MetadataType.Sources, localfp); .WithMetadata(MetadataType.Sources, localfp);
private FluentResults.Result<string> GetAbsFromLocal(ContentPackage package, string localFilePath) private FluentResults.Result<string> GetAbsoluePathFromLocal(ContentPackage package, string localFilePath)
{ {
if (Path.IsPathRooted(localFilePath)) if (Path.IsPathRooted(localFilePath))
{ {
@@ -539,13 +540,7 @@ public class StorageService : IStorageService
.WithMetadata(MetadataType.RootObject, localFilePath)); .WithMetadata(MetadataType.RootObject, localFilePath));
} }
if (package is null) Guard.IsNotNull(package, nameof(package));
{
return new FluentResults.Result<string>().WithError(
new Error($"{nameof(GetAbsFromPackage)} The package reference for {localFilePath} is null!")
.WithMetadata(MetadataType.ExceptionObject, this)
.WithMetadata(MetadataType.RootObject, localFilePath));
}
return new FluentResults.Result<string>().WithSuccess($"Path constructed") return new FluentResults.Result<string>().WithSuccess($"Path constructed")
.WithValue(System.IO.Path.GetFullPath(System.IO.Path.Combine( .WithValue(System.IO.Path.GetFullPath(System.IO.Path.Combine(
@@ -556,15 +551,9 @@ public class StorageService : IStorageService
localFilePath))); localFilePath)));
} }
public FluentResults.Result<string> GetAbsFromPackage(ContentPackage package, string localFilePath) public FluentResults.Result<string> GetAbsoluePathFromPackage(ContentPackage package, string localFilePath)
{ {
if (package is null) Guard.IsNotNull(package, nameof(package));
{
return new FluentResults.Result<string>().WithError(
new Error($"{nameof(GetAbsFromPackage)} The package reference for {localFilePath} is null!")
.WithMetadata(MetadataType.ExceptionObject, this)
.WithMetadata(MetadataType.RootObject, localFilePath));
}
if (localFilePath.IsNullOrWhiteSpace()) if (localFilePath.IsNullOrWhiteSpace())
{ {
@@ -0,0 +1,22 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using Barotrauma.LuaCs.Data;
using Barotrauma.LuaCs.Services.Processing;
using FluentResults;
namespace Barotrauma.LuaCs.Services;
public interface IModConfigService : IService
{
/// <summary>
/// Loads or dynamically generates a <see cref="IModConfigInfo"/> for the given <see cref="ContentPackage"/>.
/// <br/> Throws a <see cref="NullReferenceException"/> if the package is null.
/// </summary>
/// <param name="src"></param>
/// <returns></returns>
Task<Result<IModConfigInfo>> CreateConfigAsync([NotNull]ContentPackage src);
Task<ImmutableArray<(ContentPackage Source, Result<IModConfigInfo> Config)>> CreateConfigsAsync(ImmutableArray<ContentPackage> src);
}
@@ -53,7 +53,7 @@ public interface IStorageService : IService
ImmutableArray<(string, FluentResults.Result<byte[]>)> LoadPackageBinaryFiles(ContentPackage package, ImmutableArray<string> localFilePaths); ImmutableArray<(string, FluentResults.Result<byte[]>)> LoadPackageBinaryFiles(ContentPackage package, ImmutableArray<string> localFilePaths);
ImmutableArray<(string, FluentResults.Result<string>)> LoadPackageTextFiles(ContentPackage package, ImmutableArray<string> localFilePaths); ImmutableArray<(string, FluentResults.Result<string>)> LoadPackageTextFiles(ContentPackage package, ImmutableArray<string> localFilePaths);
FluentResults.Result<ImmutableArray<string>> FindFilesInPackage(ContentPackage package, string localSubfolder, string regexFilter, bool searchRecursively); FluentResults.Result<ImmutableArray<string>> FindFilesInPackage(ContentPackage package, string localSubfolder, string regexFilter, bool searchRecursively);
FluentResults.Result<string> GetAbsFromPackage(ContentPackage package, string localFilePath); FluentResults.Result<string> GetAbsoluePathFromPackage(ContentPackage package, string localFilePath);
// async // async
// singles // singles
Task<FluentResults.Result<XDocument>> LoadPackageXmlAsync(ContentPackage package, string localFilePath); Task<FluentResults.Result<XDocument>> LoadPackageXmlAsync(ContentPackage package, string localFilePath);