- Config Services almost ready.

- Refactored and flattened namespaces.
This commit is contained in:
MapleWheels
2026-02-05 19:47:47 -05:00
committed by Maplewheels
parent 863ee23583
commit e75208507d
101 changed files with 350 additions and 1276 deletions
@@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using OneOf;
// ReSharper disable InconsistentNaming
namespace Barotrauma.LuaCs;
public interface IAssemblyManagementService : IPluginManagementService
{
/// <summary>
/// Searches for an assembly given it's fully qualified name, while excluding the contexts with the given Guids, if supplied.
/// </summary>
/// <param name="assemblyName">The assembly info.</param>
/// <param name="excludedContexts">Guids of excluded contexts.</param>
/// <returns><b>On Success:</b> The assembly. <br/><b>On Failure:</b> nothing.</returns>
FluentResults.Result<Assembly> GetLoadedAssembly(OneOf<AssemblyName, string> assemblyName, in Guid[] excludedContexts);
}
@@ -0,0 +1,23 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks;
using System.Xml.Linq;
using Barotrauma.LuaCs.Data;
using Barotrauma.LuaCs;
using Barotrauma.Networking;
using FluentResults;
namespace Barotrauma.LuaCs;
public partial interface IConfigService : IReusableService, ILuaConfigService
{
void RegisterSettingTypeInitializer<T>(string typeIdentifier, Func<(IConfigService ConfigService, IConfigInfo Info), T> settingFactory)
where T : class, ISettingBase;
Task<FluentResults.Result> LoadConfigsAsync(ImmutableArray<IConfigResourceInfo> configResources);
Task<FluentResults.Result> LoadConfigsProfilesAsync(ImmutableArray<IConfigResourceInfo> configProfileResources);
FluentResults.Result DisposePackageData(ContentPackage package);
FluentResults.Result DisposeAllPackageData();
bool TryGetConfig<T>(ContentPackage package, string internalName, out T instance) where T : ISettingBase;
}
@@ -0,0 +1,40 @@
using System;
using System.Reflection;
using Barotrauma.LuaCs.Events;
using Barotrauma.LuaCs.Compatibility;
using Barotrauma.LuaCs;
namespace Barotrauma.LuaCs;
public interface IEventService : IReusableService, ILuaEventService
{
/// <summary>
///
/// </summary>
/// <param name="subscriber"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
FluentResults.Result Subscribe<T>(T subscriber) where T : class, IEvent<T>;
/// <summary>
///
/// </summary>
/// <param name="subscriber"></param>
/// <typeparam name="T"></typeparam>
void Unsubscribe<T>(T subscriber) where T : class, IEvent;
/// <summary>
/// Clears all subscribers for a given event type and removes any registration to the type.
/// </summary>
/// <typeparam name="T">The event type.</typeparam>
void ClearAllEventSubscribers<T>() where T : IEvent;
/// <summary>
/// Clears all subscribers lists.
/// </summary>
void ClearAllSubscribers();
/// <summary>
/// Invokes all alive subscribers of the given event using the provided invocation factory.
/// </summary>
/// <param name="action"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
FluentResults.Result PublishEvent<T>(Action<T> action) where T : IEvent<T>;
}
@@ -0,0 +1,25 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading.Tasks;
using System.Xml.Linq;
using Barotrauma.LuaCs.Data;
using FluentResults;
namespace Barotrauma.LuaCs;
public interface IParserService<in TSrc, TOut> : IService
{
Result<TOut> TryParseResource(TSrc src);
ImmutableArray<Result<TOut>> TryParseResources(IEnumerable<TSrc> sources);
}
public interface IParserServiceAsync<in TSrc, TOut> : IService
{
Task<Result<TOut>> TryParseResourceAsync(TSrc src);
Task<ImmutableArray<Result<TOut>>> TryParseResourcesAsync(IEnumerable<TSrc> sources);
}
public interface IParserServiceOneToManyAsync<in TSrc, TOut> : IService
{
Task<Result<ImmutableArray<TOut>>> TryParseResourcesAsync(TSrc src);
}
@@ -0,0 +1,27 @@
using System;
using Barotrauma.Networking;
using FluentResults;
using Microsoft.Xna.Framework;
namespace Barotrauma.LuaCs;
/// <summary>
/// Provides console and debug logging services
/// </summary>
public interface ILoggerService : IReusableService
{
void HandleException(Exception exception, string prefix = null);
void LogError(string message);
void LogWarning(string message);
void LogMessage(string message, Color? serverColor = null, Color? clientColor = null);
void Log(string message, Color? color = null, ServerLog.MessageType messageType = ServerLog.MessageType.ServerMessage);
void LogResults(FluentResults.Result result);
#region DebugBuilds
void LogDebug(string message, Color? color = null);
void LogDebugWarning(string message);
void LogDebugError(string message);
#endregion
}
@@ -0,0 +1,42 @@
namespace Barotrauma.LuaCs;
/// <summary>
/// Provides access to data from the current <see cref="LuaCsSetup"/>.
/// </summary>
public interface ILuaCsInfoProvider : IService
{
/// <summary>
/// Whether C# plugin code is enabled.
/// </summary>
public bool IsCsEnabled { get; }
/// <summary>
/// Whether the popup error GUI should be hidden/suppressed.
/// </summary>
public bool DisableErrorGUIOverlay { get; }
/// <summary>
/// Whether usernames are anonymized or show in logs.
/// </summary>
public bool HideUserNamesInLogs { get; }
/// <summary>
/// The SteamId of the Workshop LuaCs CPackage in use, if available.
/// </summary>
public ulong LuaForBarotraumaSteamId { get; }
/// <summary>
/// Restrict the maximum size of messages sent over the network.
/// </summary>
public bool RestrictMessageSize { get; }
/// <summary>
/// The local save path for all local data storage for mods.
/// </summary>
public string LocalDataSavePath { get; }
/// <summary>
/// The current state of the Execution State Machine.
/// </summary>
public RunState CurrentRunState { get; }
}
@@ -0,0 +1,61 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Reflection;
using System.Threading.Tasks;
using Barotrauma.LuaCs.Data;
using FluentResults;
using MoonSharp.Interpreter;
using MoonSharp.Interpreter.Interop;
namespace Barotrauma.LuaCs;
public interface ILuaScriptManagementService : IReusableService
{
#region Script_Ops
object? GetGlobalTableValue(string tableName);
FluentResults.Result<DynValue> DoString(string code);
/// <summary>
/// Parses and loads script sources (code) into a memory cache without executing it.
/// </summary>
/// <param name="resourcesInfo"></param>
/// <returns></returns>
// [Required]
Task<FluentResults.Result> LoadScriptResourcesAsync(ImmutableArray<ILuaScriptResourceInfo> resourcesInfo);
/// <summary>
/// Executes already loaded into memory scripts data, in the supplied order.
/// </summary>
/// <param name="executionOrder"></param>
/// <returns></returns>
// [Required]
FluentResults.Result ExecuteLoadedScripts(ImmutableArray<ILuaScriptResourceInfo> executionOrder);
/// <summary>
///
/// </summary>
/// <param name="package"></param>
/// <returns></returns>
// [Required]
FluentResults.Result DisposePackageResources(ContentPackage package);
/// <summary>
/// Calls dispose on, and clears active refs for, currently running scripts. Does not clear caches.
/// </summary>
/// <returns></returns>
FluentResults.Result UnloadActiveScripts();
/// <summary>
/// Unloads all scripts and clears all caches/references.
/// </summary>
/// <returns></returns>
/// <remarks>May be functionally equivalent to <see cref="IReusableService.Reset"/></remarks>
FluentResults.Result DisposeAllPackageResources();
#endregion
}
@@ -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;
using FluentResults;
namespace Barotrauma.LuaCs;
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);
}
@@ -0,0 +1,31 @@
using System;
using Barotrauma.LuaCs.Data;
using Barotrauma.LuaCs;
using Barotrauma.LuaCs.Compatibility;
using Barotrauma.Networking;
namespace Barotrauma.LuaCs;
internal delegate void NetMessageReceived(IReadMessage netMessage);
internal partial interface INetworkingService : IReusableService, ILuaCsNetworking, IEntityNetworkingService
{
bool IsActive { get; }
bool IsSynchronized { get; }
public IWriteMessage Start(Guid netId);
public void Receive(Guid netId, NetMessageReceived action);
#if SERVER
public void Send(IWriteMessage netMessage, NetworkConnection connection = null, DeliveryMethod deliveryMethod = DeliveryMethod.Reliable);
#elif CLIENT
public void Send(IWriteMessage netMessage, DeliveryMethod deliveryMethod = DeliveryMethod.Reliable);
#endif
}
public interface IEntityNetworkingService
{
public ulong GetNetworkIdForInstance(INetworkSyncEntity entity);
public void RegisterNetVar(INetworkSyncEntity netVar);
public void SendNetVar(INetworkSyncEntity netVar);
}
@@ -0,0 +1,28 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Threading.Tasks;
using Barotrauma.Extensions;
using Barotrauma.LuaCs.Data;
using FluentResults;
namespace Barotrauma.LuaCs;
public interface IPackageManagementService : IReusableService
{
public FluentResults.Result LoadPackageInfo(ContentPackage package);
public FluentResults.Result LoadPackagesInfo(ImmutableArray<ContentPackage> packages);
public FluentResults.Result ExecuteLoadedPackages(ImmutableArray<ContentPackage> executionOrder, bool executeCsAssemblies);
public FluentResults.Result SyncLoadedPackagesList(ImmutableArray<ContentPackage> packages);
public FluentResults.Result StopRunningPackages();
public FluentResults.Result UnloadPackage(ContentPackage package);
public FluentResults.Result UnloadPackages(ImmutableArray<ContentPackage> packages);
public FluentResults.Result UnloadAllPackages();
public ImmutableArray<ContentPackage> GetAllLoadedPackages();
public ImmutableArray<ContentPackage> GetLoadedAssemblyPackages();
public bool IsPackageRunning(ContentPackage package);
public bool IsAnyPackageLoaded();
public bool IsAnyPackageRunning();
}
@@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Reflection;
using Barotrauma.LuaCs.Data;
using Microsoft.CodeAnalysis;
namespace Barotrauma.LuaCs;
public interface IPluginManagementService : IReusableService
{
/// <summary>
/// Gets all types in searched <see cref="IAssemblyLoaderService"/> that implement the type supplied.
/// </summary>
/// <param name="includeInterfaces"></param>
/// <param name="includeAbstractTypes"></param>
/// <param name="includeDefaultContext"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
FluentResults.Result<ImmutableArray<Type>> GetImplementingTypes<T>(
bool includeInterfaces = false,
bool includeAbstractTypes = false,
bool includeDefaultContext = true);
/// <summary>
/// Tries to find the type given the fully qualified name and filters.
/// </summary>
/// <param name="typeName"></param>
/// <param name="isByRefType"></param>
/// <param name="includeInterfaces"></param>
/// <param name="includeDefaultContext"></param>
/// <returns></returns>
Type GetType(string typeName, bool isByRefType = false, bool includeInterfaces = false, bool includeDefaultContext = true);
/// <summary>
///
/// </summary>
/// <param name="executionOrder"></param>
/// <param name="excludeAlreadyRunningPackages"></param>
/// <returns></returns>
FluentResults.Result ActivatePluginInstances(ImmutableArray<ContentPackage> executionOrder, bool excludeAlreadyRunningPackages = true);
/// <summary>
/// Loads the provided assembly resources in the order of their dependencies and intra-mod priority load order.
/// </summary>
/// <param name="resources"></param>
/// <returns>Success/Failure and list of failed resources, if any.</returns>
FluentResults.Result LoadAssemblyResources(ImmutableArray<IAssemblyResourceInfo> resources);
/// <summary>
/// Unloads all managed <see cref="IAssemblyPlugin"/>, <see cref="Assembly"/>, and <see cref="IAssemblyLoaderService"/>s.
/// </summary>
/// <returns>Success of the operation. <br/><b>Note: does not guarantee .NET runtime assembly unloading success.</b></returns>
FluentResults.Result UnloadManagedAssemblies();
}
@@ -0,0 +1,50 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Reflection;
using Barotrauma.LuaCs.Data;
namespace Barotrauma.LuaCs;
public interface IPluginService : IReusableService
{
bool IsAssemblyLoaded(string friendlyName);
/// <summary>
/// Loads the assemblies for the given information
/// </summary>
/// <param name="assemblyResourcesInfo"></param>
/// <param name="injectServices"></param>
/// <param name="typeInstances"></param>
/// <typeparam name="T"></typeparam>
/// <returns></returns>
FluentResults.Result LoadAndInstanceTypes<T>(IEnumerable<IAssemblyResourceInfo> assemblyResourcesInfo, bool injectServices, out ImmutableArray<T> typeInstances) where T : class, IAssemblyPlugin;
FluentResults.Result<ImmutableArray<T>> GetLoadedPluginTypesInPackage<T>() where T : class, IAssemblyPlugin;
/// <summary>
/// Advances the loading/execution state of the plugin. IMPORTANT: You cannot set the execution state of plugins
/// to 'Disposed'. You must instead call the 'DisposePlugins' method.
/// </summary>
/// <param name="newState"></param>
/// <returns></returns>
FluentResults.Result AdvancePluginStates(PluginRunState newState);
/// <summary>
/// Disposes of all running plugins hosted by the service and releases their references to allow unloading.
/// </summary>
/// <returns>Success of the operation. Returns false if any plugin threw errors during disposal.</returns>
FluentResults.Result DisposePlugins();
/// <summary>
/// Gets the current plugin execution state.
/// </summary>
/// <returns></returns>
PluginRunState GetPluginRunState();
}
public enum PluginRunState
{
Instanced=0,
PreInitialization=1,
Initialized=2,
LoadingCompleted=3,
Disposed=4
}
@@ -0,0 +1,54 @@
using System.Collections.Immutable;
namespace Barotrauma.LuaCs;
public interface ISafeStorageService : IStorageService, ISafeStorageValidation { }
public interface ISafeStorageValidation
{
/// <summary>
/// Checks the given file path to see if it can be read. This includes any permissions, whitelists and OS checks.
/// </summary>
/// <param name="path">The absolute path to the file.</param>
/// <param name="readOnly">Whether to only check for read permissions only, or full RWM if false.</param>
/// <param name="checkWhitelistOnly">Whether to only check if the file is safe to access, without checking accessibility at the OS level.</param>
/// <returns>Whether the file is accessible.</returns>
bool IsFileAccessible(string path, bool readOnly, bool checkWhitelistOnly = true);
/// <summary>
/// Adds the given path to the specified whitelists.
/// </summary>
/// <param name="path">The path to the file, exactly as it will be passed to the Try(Load|Save) methods in <see cref="StorageService"/>.</param>
/// <param name="readOnly">Whether to add it to the read whitelist only, or Read+Write whitelists.</param>
void AddFileToWhitelist(string path, bool readOnly = true);
/// <summary>
/// Adds the given collection of file paths to whitelists (Read|+Write)
/// </summary>
/// <param name="paths">The paths to the files, formatted exactly as it will be passed to the Try(Load|Save) methods in <see cref="StorageService"/>.</param>
/// <param name="readOnly">Whether to add it to the read whitelist only, or Read+Write whitelists.</param>
void AddFilesToWhitelist(ImmutableArray<string> paths, bool readOnly = true);
/// <summary>
/// Removes the given path from all whitelists (Read|+Write).
/// </summary>
/// <param name="path"></param>
void RemoveFileFromAllWhitelists(string path);
/// <summary>
/// Sets the whitelist filtering for read-only file permissions for the instance. Overwrites previous list.
/// </summary>
/// <param name="filePaths">List of file paths allowed, as will be passed to the <see cref="StorageService"/> Try(Load|Save) methods.</param>
FluentResults.Result SetReadOnlyWhitelist(ImmutableArray<string> filePaths);
/// <summary>
/// Sets the whitelist filtering for read & write file permissions for the instance. Overwrites previous lists.
/// </summary>
/// <param name="filePaths">List of file paths allowed, as will be passed to the <see cref="StorageService"/> Try(Load|Save) methods.</param>
FluentResults.Result SetReadWriteWhitelist(ImmutableArray<string> filePaths);
/// <summary>
/// Deletes all paths from all white lists.
/// </summary>
void ClearAllWhitelists();
}
@@ -0,0 +1,37 @@
using System;
using Microsoft.Toolkit.Diagnostics;
namespace Barotrauma.LuaCs;
/// <summary>
/// Defines a service that can be reset to it's post-constructor state and reused without needing to be disposed.
/// Intended for persistent services.
/// </summary>
public interface IReusableService : IService
{
/// <summary>
/// Returns the service to its original state (post-instantiation).
/// Allows a service instance to be reused without disposing of the instance.
/// </summary>
FluentResults.Result Reset();
}
/// <summary>
/// Base interface inherited by all services.
/// </summary>
/// <exception cref="ObjectDisposedException">Throws exception if `IsDisposed` return true.</exception>
public interface IService : IDisposable
{
bool IsDisposed { get; }
public void CheckDisposed()
{
if (IsDisposed)
ThrowHelper.ThrowObjectDisposedException($"Tried to call method on disposed object '{this.GetType().Name}'!");
}
static void CheckDisposed(IService service)
{
if (service.IsDisposed)
ThrowHelper.ThrowObjectDisposedException($"Tried to call method on disposed object '{service.GetType().Name}'!");
}
}
@@ -0,0 +1,122 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using LightInject;
namespace Barotrauma.LuaCs;
/// <summary>
/// Provides instancing and management of IServices.
/// </summary>
public interface IServicesProvider
{
#region Type_Registration
/// <summary>
/// Registers a type as a service for a given interface.
/// </summary>
/// <param name="lifetime"></param>
/// <param name="lifetimeInstance"></param>
/// <typeparam name="TSvcInterface"></typeparam>
/// <typeparam name="TService"></typeparam>
void RegisterServiceType<TSvcInterface, TService>(ServiceLifetime lifetime, ILifetime lifetimeInstance = null) where TSvcInterface : class, IService where TService : class, IService, TSvcInterface;
/// <summary>
/// Registers a type as a service for a given interface that can be requested by name.
/// </summary>
/// <param name="name"></param>
/// <param name="lifetime"></param>
/// <param name="lifetimeInstance"></param>
/// <typeparam name="TSvcInterface"></typeparam>
/// <typeparam name="TService"></typeparam>
void RegisterServiceType<TSvcInterface, TService>(string name, ServiceLifetime lifetime, ILifetime lifetimeInstance = null) where TSvcInterface : class, IService where TService : class, IService, TSvcInterface;
/// <summary>
/// Called whenever a new service type for a given interface is implemented.
/// Args[0]: Interface type
/// Args[1]: Implementing type
/// </summary>
event System.Action<Type, Type> OnServiceRegistered;
/// <summary>
/// Registers a factory for resolving the service type.
/// </summary>
/// <param name="factory"></param>
/// <typeparam name="TSvcInterface"></typeparam>
void RegisterServiceResolver<TSvcInterface>(Func<ServiceContainer, TSvcInterface> factory) where TSvcInterface : class, IService;
/// <summary>
/// Runs compilation of registered services.
/// </summary>
public void Compile();
#endregion
#region Services_Instancing_Injection
/// <summary>
/// Injects services into the properties of already instanced objects.
/// </summary>
/// <param name="inst"></param>
/// <typeparam name="T"></typeparam>
void InjectServices<T>(T inst) where T : class;
/// <summary>
/// Tries to get a service for the given interface, returns success/failure.
/// </summary>
/// <param name="service"></param>
/// <typeparam name="TSvcInterface"></typeparam>
/// <returns></returns>
bool TryGetService<TSvcInterface>(out TSvcInterface service) where TSvcInterface : class, IService;
/// <summary>
/// Tries to get a service for the given interface, throws an exception upon failure.
/// </summary>
/// <typeparam name="TSvcInterface"></typeparam>
/// <returns></returns>
TSvcInterface GetService<TSvcInterface>() where TSvcInterface : class, IService;
/// <summary>
/// Tries to get a service for the given name and interface, returns success/failure.
/// </summary>
/// <param name="name"></param>
/// <param name="service"></param>
/// <typeparam name="TSvcInterface"></typeparam>
/// <returns></returns>
bool TryGetService<TSvcInterface>(string name, out TSvcInterface service) where TSvcInterface : class, IService;
/// <summary>
/// Called whenever a new service is created/instanced.
/// Args[0]: The interface type of the service.
/// Args[1]: The instance of the service.
/// </summary>
event System.Action<Type, IService> OnServiceInstanced;
#endregion
#region ActiveServices
/// <summary>
/// Returns all services for the given interface.
/// </summary>
/// <typeparam name="TSvc"></typeparam>
/// <returns></returns>
ImmutableArray<TSvc> GetAllServices<TSvc>() where TSvc : class, IService;
#endregion
// Notes: Left public due to the common use of Publicizers
#region Internal_Use
/// <summary>
/// Notes: Internal use only if hosted by LuaCsForBarotrauma. Disposes of all services and resets DI container. Warning: unable to dispose of services held by other objects.
/// </summary>
void DisposeAndReset();
#endregion
}
public enum ServiceLifetime
{
Transient, Singleton, PerThread, Invalid, Custom
}
@@ -0,0 +1,84 @@
using System;
using System.Collections.Immutable;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Linq;
using FluentResults;
namespace Barotrauma.LuaCs;
public interface IStorageService : IService
{
bool UseCaching { get; set; }
/// <summary>
/// Deletes all cached file data.
/// </summary>
void PurgeCache();
/// <summary>
/// Deletes the data for the supplied file path from the data cache.
/// </summary>
/// <param name="absolutePath"></param>
void PurgeFileFromCache(string absolutePath);
/// <summary>
/// Deletes the data from the supplied file paths from the data cache.
/// </summary>
/// <param name="absolutePaths"></param>
void PurgeFilesFromCache(params string[] absolutePaths);
// -- local game folder storage
FluentResults.Result<XDocument> LoadLocalXml(ContentPackage package, string localFilePath);
FluentResults.Result<byte[]> LoadLocalBinary(ContentPackage package, string localFilePath);
FluentResults.Result<string> LoadLocalText(ContentPackage package, string localFilePath);
FluentResults.Result SaveLocalXml(ContentPackage package, string localFilePath, XDocument document);
FluentResults.Result SaveLocalBinary(ContentPackage package, string localFilePath, in byte[] bytes);
FluentResults.Result SaveLocalText(ContentPackage package, string localFilePath, in string text);
// async
Task<FluentResults.Result<XDocument>> LoadLocalXmlAsync(ContentPackage package, string localFilePath);
Task<FluentResults.Result<byte[]>> LoadLocalBinaryAsync(ContentPackage package, string localFilePath);
Task<FluentResults.Result<string>> LoadLocalTextAsync(ContentPackage package, string localFilePath);
Task<FluentResults.Result> SaveLocalXmlAsync(ContentPackage package, string localFilePath, XDocument document);
Task<FluentResults.Result> SaveLocalBinaryAsync(ContentPackage package, string localFilePath, byte[] bytes);
Task<FluentResults.Result> SaveLocalTextAsync(ContentPackage package, string localFilePath, string text);
// -- package directory
// singles
Result<XDocument> LoadPackageXml(ContentPath filePath);
Result<byte[]> LoadPackageBinary(ContentPath filePath);
Result<string> LoadPackageText(ContentPath filePath);
// collections
ImmutableArray<(ContentPath, Result<XDocument>)> LoadPackageXmlFiles(ImmutableArray<ContentPath> filePaths);
ImmutableArray<(ContentPath, Result<byte[]>)> LoadPackageBinaryFiles(ImmutableArray<ContentPath> filePaths);
ImmutableArray<(ContentPath, Result<string>)> LoadPackageTextFiles(ImmutableArray<ContentPath> filePaths);
FluentResults.Result<ImmutableArray<string>> FindFilesInPackage(ContentPackage package, string localSubfolder, string regexFilter, bool searchRecursively);
// async
// singles
Task<Result<XDocument>> LoadPackageXmlAsync(ContentPath filePath);
Task<Result<byte[]>> LoadPackageBinaryAsync(ContentPath filePath);
Task<Result<string>> LoadPackageTextAsync(ContentPath filePath);
// collections
Task<ImmutableArray<(ContentPath, Result<XDocument>)>> LoadPackageXmlFilesAsync(ImmutableArray<ContentPath> filePaths);
Task<ImmutableArray<(ContentPath, Result<byte[]>)>> LoadPackageBinaryFilesAsync(ImmutableArray<ContentPath> filePaths);
Task<ImmutableArray<(ContentPath, Result<string>)>> LoadPackageTextFilesAsync(ImmutableArray<ContentPath> filePaths);
// -- absolute paths
FluentResults.Result<XDocument> TryLoadXml(string filePath, Encoding encoding = null);
FluentResults.Result<string> TryLoadText(string filePath, Encoding encoding = null);
FluentResults.Result<byte[]> TryLoadBinary(string filePath);
FluentResults.Result TrySaveXml(string filePath, in XDocument document, Encoding encoding = null);
FluentResults.Result TrySaveText(string filePath, in string text, Encoding encoding = null);
FluentResults.Result TrySaveBinary(string filePath, in byte[] bytes);
FluentResults.Result<bool> FileExists(string filePath);
FluentResults.Result<bool> DirectoryExists(string directoryPath);
//async
Task<FluentResults.Result<XDocument>> TryLoadXmlAsync(string filePath, Encoding encoding = null);
Task<FluentResults.Result<string>> TryLoadTextAsync(string filePath, Encoding encoding = null);
Task<FluentResults.Result<byte[]>> TryLoadBinaryAsync(string filePath);
Task<FluentResults.Result> TrySaveXmlAsync(string filePath, XDocument document, Encoding encoding = null);
Task<FluentResults.Result> TrySaveTextAsync(string filePath, string text, Encoding encoding = null);
Task<FluentResults.Result> TrySaveBinaryAsync(string filePath, byte[] bytes);
}