From 0bfceacaf3361f25fffa87fcb4bc1aa6845de56e Mon Sep 17 00:00:00 2001 From: MapleWheels Date: Tue, 13 Jan 2026 14:14:32 -0500 Subject: [PATCH] - Completed most of PackageManagementService.cs - Some areas of code need to be rewritten for the simplified loading and execution process. --- .../ClientSource/LuaCs/LuaCsSetup.cs | 7 +- .../LuaCs/Data/ServicesConfigData.cs | 18 + .../SharedSource/LuaCs/LuaCsSetup.cs | 55 +- .../LuaCs/Services/ConfigService.cs | 573 ++---------------- .../Services/LuaScriptManagementService.cs | 4 +- .../Services/PackageManagementService.cs | 252 ++++++-- .../LuaCs/Services/PluginManagementService.cs | 2 +- .../Services/_Interfaces/IConfigService.cs | 1 + .../ILuaScriptManagementService.cs | 5 +- .../_Interfaces/IPackageManagementService.cs | 14 +- .../_Interfaces/IPluginManagementService.cs | 5 +- 11 files changed, 310 insertions(+), 626 deletions(-) diff --git a/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSetup.cs b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSetup.cs index 894641c17..08f5522c3 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSetup.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSetup.cs @@ -25,8 +25,9 @@ namespace Barotrauma public void CheckCsEnabled() { - - var csharpMods = PackageManagementService.Assemblies + throw new NotImplementedException($"Replace PMS.Assemblies with checks on ContentPackageManager.EnabledPackages"); + + /*var csharpMods = PackageManagementService.Assemblies .GroupBy(ass => ass.OwnerPackage) .Select(grp => grp.Key) .Where(ContentPackageManager.EnabledPackages.All.Contains) @@ -66,7 +67,7 @@ namespace Barotrauma { this.IsCsEnabled.TrySetValue(false); return true; - }; + };*/ } /// diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Data/ServicesConfigData.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Data/ServicesConfigData.cs index cce3a273b..f24283ac5 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Data/ServicesConfigData.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Data/ServicesConfigData.cs @@ -10,6 +10,7 @@ using System.Security.AccessControl; using Barotrauma.LuaCs.Services; using Barotrauma.Networking; using FluentResults; +using OneOf.Types; namespace Barotrauma.LuaCs.Data; @@ -224,3 +225,20 @@ public record LuaScriptServicesConfig : ILuaScriptServicesConfig public bool IsDisposed => false; } + +// --- Package Management Service +public interface IPackageManagementServiceConfig : IService +{ + bool IsCsEnabled { get; } +} + +public class PackageManagementServiceConfig : IPackageManagementServiceConfig +{ + public void Dispose() + { + // ignored + } + + public bool IsDisposed => false; + public bool IsCsEnabled => true; +} diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs index 95d7a92af..0ea4484cf 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs @@ -340,7 +340,6 @@ namespace Barotrauma foreach (var package in toRemove) _toUnload.Enqueue(package); - ProcessPackagesListDifferences(); } @@ -358,16 +357,14 @@ namespace Barotrauma while (_toUnload.TryDequeue(out var cp)) { - LuaScriptManagementService.DisposePackageResources(cp); - ConfigService.DisposePackageData(cp); - PackageManagementService.DisposePackageInfos(cp); + } var ls = new List(); while (_toLoad.TryDequeue(out var cp)) { - if (PackageManagementService.LoadPackageInfosAsync(cp).GetAwaiter().GetResult() is + if (PackageManagementService.LoadPackageInfo(cp) is { IsFailed: true } failure) { Logger.LogError($"Failed to load package infos for {cp.Name}"); @@ -456,8 +453,7 @@ namespace Barotrauma return; // load core - var result1 = PackageManagementService.LoadPackageInfosAsync(ContentPackageManager.VanillaCorePackage) - .GetAwaiter().GetResult(); + var result1 = PackageManagementService.LoadPackageInfo(ContentPackageManager.VanillaCorePackage); if (result1.IsFailed) { Logger.LogError($"Unable to load LuaCs CorePackage resources! Running in degraded mode."); @@ -477,16 +473,9 @@ namespace Barotrauma void LoadContentPackagesInfos(IReadOnlyList packages) { - var result2 = PackageManagementService.LoadPackagesInfosAsync(packages) - .GetAwaiter().GetResult(); - - foreach (var entry in result2) - { - if (entry.Item2.IsSuccess) - Logger.LogMessage($"Successfully parsed package: {entry.Item1.Name}"); - else if (entry.Item2.IsFailed) - Logger.LogResults(entry.Item2); - } + var result2 = PackageManagementService.LoadPackagesInfo([..packages]); + if (result2.IsFailed) + Logger.LogResults(result2); } void LoadStaticAssets() @@ -500,7 +489,7 @@ namespace Barotrauma return; while (_toUnload.TryDequeue(out var cp)) - PackageManagementService.DisposePackageInfos(cp); + PackageManagementService.UnloadPackage(cp); LoadStaticAssetsAsync(PackageManagementService.GetAllLoadedPackages()).GetAwaiter().GetResult(); LoadLuaCsConfig(); @@ -543,11 +532,13 @@ namespace Barotrauma async Task LoadStaticAssetsAsync(IReadOnlyList packages) { - var cfgRes = ImmutableArray.Empty; - var luaRes = ImmutableArray.Empty; + throw new NotImplementedException(); + /*var cfgRes = ImmutableArray.Empty; + var luaRes = ImmutableArray.Empty; + var tasksBuilder = ImmutableArray.CreateBuilder(); - + //---- get resource infos tasksBuilder.AddRange( new Func(async () => @@ -568,10 +559,10 @@ namespace Barotrauma ThreadPool.QueueUserWorkItem(state => Logger.LogResults((FluentResults.Result)state), res.ToResult()); })()); - + await Task.WhenAll(tasksBuilder.MoveToImmutable()); tasksBuilder.Clear(); - + //---- load resources tasksBuilder.AddRange(new Func(async () => { @@ -586,12 +577,12 @@ namespace Barotrauma Logger.LogResults(res); })()); - await Task.WhenAll(tasksBuilder.MoveToImmutable()); + await Task.WhenAll(tasksBuilder.MoveToImmutable());*/ } void RunScripts() { - if (!IsStaticAssetsLoaded) + /*if (!IsStaticAssetsLoaded) { throw new InvalidOperationException($"{nameof(RunScripts)} cannot load assets in the '{CurrentRunState}' state."); } @@ -661,23 +652,23 @@ namespace Barotrauma LuaScriptManagementService.ExecuteLoadedScripts(); if (CurrentRunState < RunState.Running) - _runState = RunState.Running; + _runState = RunState.Running;*/ } void UnloadContentPackageInfos() { - if (IsStaticAssetsLoaded) + /*if (IsStaticAssetsLoaded) { throw new InvalidOperationException($"{nameof(UnloadStaticAssets)}: Cannot unload static assets when the current run state is {CurrentRunState}."); } PackageManagementService.Reset(); - _toUnload.Clear(); + _toUnload.Clear();*/ } void UnloadStaticAssets() { - if (IsCodeRunning) + /*if (IsCodeRunning) { throw new InvalidOperationException($"{nameof(UnloadStaticAssets)}: Cannot unload static assets when the current run state is {CurrentRunState}."); } @@ -689,12 +680,12 @@ namespace Barotrauma if (CurrentRunState >= RunState.Configuration) { _runState = RunState.Parsed; - } + }*/ } void StopScripts() { - EventService.ClearAllSubscribers(); + /*EventService.ClearAllSubscribers(); LuaScriptManagementService.UnloadActiveScripts(); PluginManagementService.UnloadManagedAssemblies(); SubscribeToLuaCsEvents(); @@ -702,7 +693,7 @@ namespace Barotrauma if (IsCodeRunning) { _runState = RunState.Configuration; - } + }*/ } diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/ConfigService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/ConfigService.cs index df6e6c39f..f3f8d5f65 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/ConfigService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/ConfigService.cs @@ -23,668 +23,179 @@ namespace Barotrauma.LuaCs.Services; public partial class ConfigService : IConfigService { - //--- Internals - public ConfigService(IParserServiceAsync> configProfileResourceParser, - IParserServiceAsync> configResourceParser, IEventService eventService, System.Lazy storageService) - { - _configProfileResourceParser = configProfileResourceParser; - _configResourceParser = configResourceParser; - _eventService = eventService; - _storageService = storageService; - this._base = this; - } - - // data, states - private readonly IService _base; - private int _isDisposed = 0; - private readonly ConcurrentDictionary>> _configTypeInitializers = new(); - private readonly ConcurrentDictionary<(ContentPackage Package, string ConfigName), IConfigBase> _configs = new(); - private readonly ConcurrentDictionary> _packageConfigReverseLookup = new(); - private readonly ConcurrentDictionary<(ContentPackage Package, string ProfileName), ImmutableArray<(string ConfigName, OneOf.OneOf Value)>> _configProfiles = new(); - private readonly ConcurrentDictionary> _packageProfilesReverseLookup = new(); - private readonly ConcurrentDictionary _packageNameMap= new(); - - private readonly AsyncReaderWriterLock _disposeOpsLock = new(); - - // extern services - private readonly IParserServiceAsync> _configResourceParser; - private readonly IParserServiceAsync> _configProfileResourceParser; - private readonly IEventService _eventService; - private readonly System.Lazy _storageService; - - //--- GC - public bool IsDisposed => ModUtils.Threading.GetBool(ref _isDisposed); - public void Dispose() { - // stop all ops - using var lck = _disposeOpsLock.AcquireWriterLock().GetAwaiter().GetResult(); - // set flag - ModUtils.Threading.SetBool(ref _isDisposed, true); - - _configTypeInitializers.Clear(); - if (!_configs.IsEmpty) - { - foreach (var config in _configs) - { - if (config.Value is IDisposable disposable) - disposable.Dispose(); - config.Value.OnValueChanged -= this.SaveConfigEvent; - } - _configs.Clear(); - } - - _configProfiles.Clear(); - _packageConfigReverseLookup.Clear(); - _packageNameMap.Clear(); - _packageProfilesReverseLookup.Clear(); - - GC.SuppressFinalize(this); + throw new NotImplementedException(); } - + + public bool IsDisposed { get; } public FluentResults.Result Reset() { - using var lck = _disposeOpsLock.AcquireWriterLock().GetAwaiter().GetResult(); - _base.CheckDisposed(); - - _configTypeInitializers.Clear(); - _configs.Clear(); - _configProfiles.Clear(); - _packageConfigReverseLookup.Clear(); - _packageNameMap.Clear(); - _packageProfilesReverseLookup.Clear(); - - return FluentResults.Result.Ok(); + throw new NotImplementedException(); } - //--- API contracts - // Notes: - // -- Lua Interface uses strong types due to lua limitations. May be required to move API to an adapter class - // to allow testing abstraction. - // -- Lua interface should not propagate errors. - #region LuaInterface - - private bool TryGetConfigValue(string packageName, string configName, out T value) where T : IEquatable - { - value = default; - using var lck = _disposeOpsLock.AcquireReaderLock().GetAwaiter().GetResult(); - if (ModUtils.Threading.GetBool(ref _isDisposed)) - return false; - if (!_packageNameMap.TryGetValue(packageName, out var package)) - return false; - if (!_configs.TryGetValue((package, configName), out var config)) - return false; - if (config is not IConfigEntry entry) - return false; - value = entry.Value; - return true; - } - public bool TryGetConfigBool(string packageName, string configName, out bool value) { - return TryGetConfigValue(packageName, configName, out value); + throw new NotImplementedException(); } public bool TryGetConfigInt(string packageName, string configName, out int value) { - return TryGetConfigValue(packageName, configName, out value); + throw new NotImplementedException(); } public bool TryGetConfigFloat(string packageName, string configName, out float value) { - return TryGetConfigValue(packageName, configName, out value); + throw new NotImplementedException(); } public bool TryGetConfigNumber(string packageName, string configName, out double value) { - return TryGetConfigValue(packageName, configName, out value); + throw new NotImplementedException(); } public bool TryGetConfigString(string packageName, string configName, out string value) { - return TryGetConfigValue(packageName, configName, out value); + throw new NotImplementedException(); } public bool TryGetConfigVector2(string packageName, string configName, out Vector2 value) { - return TryGetConfigValue(packageName, configName, out value); + throw new NotImplementedException(); } public bool TryGetConfigVector3(string packageName, string configName, out Vector3 value) { - return TryGetConfigValue(packageName, configName, out value); + throw new NotImplementedException(); } public bool TryGetConfigColor(string packageName, string configName, out Color value) { - return TryGetConfigValue(packageName, configName, out value); + throw new NotImplementedException(); } public bool TryGetConfigList(string packageName, string configName, out IReadOnlyList value) { - value = null; - using var lck = _disposeOpsLock.AcquireReaderLock().GetAwaiter().GetResult(); - if (ModUtils.Threading.GetBool(ref _isDisposed)) - return false; - if (!_packageNameMap.TryGetValue(packageName, out var package)) - return false; - if (!_configs.TryGetValue((package, configName), out var config)) - return false; - if (config is not IConfigList entry) - return false; - value = entry.Options; - return value is not null && value.Count > 0; - } - - private void SetConfigValue(string packageName, string configName, T value) where T : IEquatable - { - using var lck = _disposeOpsLock.AcquireReaderLock().GetAwaiter().GetResult(); - if (ModUtils.Threading.GetBool(ref _isDisposed)) - return; - if (!_packageNameMap.TryGetValue(packageName, out var package)) - return; - if (!_configs.TryGetValue((package, configName), out var config)) - return; - if (config is not IConfigEntry entry) - return; - entry.TrySetValue(value); + throw new NotImplementedException(); } public void SetConfigBool(string packageName, string configName, bool value) { - SetConfigValue(packageName, configName, value); + throw new NotImplementedException(); } public void SetConfigInt(string packageName, string configName, int value) { - SetConfigValue(packageName, configName, value); + throw new NotImplementedException(); } public void SetConfigFloat(string packageName, string configName, float value) { - SetConfigValue(packageName, configName, value); + throw new NotImplementedException(); } public void SetConfigNumber(string packageName, string configName, double value) { - SetConfigValue(packageName, configName, value); + throw new NotImplementedException(); } public void SetConfigString(string packageName, string configName, string value) { - SetConfigValue(packageName, configName, value); + throw new NotImplementedException(); } public void SetConfigVector2(string packageName, string configName, Vector2 value) { - SetConfigValue(packageName, configName, value); + throw new NotImplementedException(); } public void SetConfigVector3(string packageName, string configName, Vector3 value) { - SetConfigValue(packageName, configName, value); + throw new NotImplementedException(); } public void SetConfigColor(string packageName, string configName, Color value) { - SetConfigValue(packageName, configName, value); + throw new NotImplementedException(); } public void SetConfigList(string packageName, string configName, string value) { - using var lck = _disposeOpsLock.AcquireReaderLock().GetAwaiter().GetResult(); - if (ModUtils.Threading.GetBool(ref _isDisposed)) - return; - if (!_packageNameMap.TryGetValue(packageName, out var package)) - return; - if (!_configs.TryGetValue((package, configName), out var config)) - return; - if (config is not IConfigList entry) - return; - entry.TrySetValue(value); + throw new NotImplementedException(); } public bool TryApplyProfileSettings(string packageName, string profileName) { - - if (ModUtils.Threading.GetBool(ref _isDisposed)) - return false; - if (packageName.IsNullOrWhiteSpace() || profileName.IsNullOrWhiteSpace()) - return false; - ContentPackage package = null; - using (var lck = _disposeOpsLock.AcquireReaderLock().GetAwaiter().GetResult()) - { - if (!_packageNameMap.TryGetValue(packageName, out package) || package == null) - return false; - } - // exit semaphore before invocation. Note: Race condition, may require copy implementation. - return this.ApplyProfileSettings(package, profileName).IsSuccess; + throw new NotImplementedException(); } - #endregion - - public void RegisterTypeInitializer(Func> initializer, bool replaceIfExists = false) - where TData : IEquatable where TConfig : IConfigBase + public void RegisterTypeInitializer(Func> initializer, bool replaceIfExists = false) where TData : IEquatable where TConfig : IConfigBase { - using var lck = _disposeOpsLock.AcquireReaderLock().GetAwaiter().GetResult(); - _base.CheckDisposed(); - - Type dataType = typeof(TData); - if (_configTypeInitializers.ContainsKey(dataType) && !replaceIfExists) - return; - _configTypeInitializers[dataType] = (info => - { - var res = initializer(info); - if (res.IsFailed) - return FluentResults.Result.Fail($"Failed to initialize config type {dataType.Name}").WithErrors(res.Errors); - return res.Value; - }); + throw new NotImplementedException(); } - private void AddConfigInstance((ContentPackage Package, string ConfigName) key, IConfigBase instance) - { - _configs[key] = instance; - if (!_packageNameMap.ContainsKey(key.Package.Name)) - _packageNameMap[key.Package.Name] = key.Package; - if (!_packageConfigReverseLookup.TryGetValue(key.Package, out var list)) - { - list = new ConcurrentBag<(ContentPackage Package, string ConfigName)>(); - _packageConfigReverseLookup[key.Package] = list; - } - list.Add(key); - // save hook - instance.OnValueChanged += this.SaveConfigEvent; - _eventService.PublishEvent(sub => sub.OnConfigCreated(instance)); - } - - private void AddProfileInstance((ContentPackage Package, string ProfileName) key, IConfigProfileInfo profile) - { - _configProfiles[key] = profile.ProfileValues.ToImmutableArray(); - if (!_packageNameMap.ContainsKey(key.Package.Name)) - _packageNameMap[key.Package.Name] = key.Package; - if (!_packageProfilesReverseLookup.TryGetValue(key.Package, out var list)) - { - list = new ConcurrentBag<(ContentPackage Package, string ProfileName)>(); - _packageProfilesReverseLookup[key.Package] = list; - } - list.Add(key); - } - public async Task LoadConfigsAsync(ImmutableArray configResources) { - using var lck = await _disposeOpsLock.AcquireReaderLock(); - _base.CheckDisposed(); - - if (configResources.IsDefaultOrEmpty) - return FluentResults.Result.Fail($"{nameof(LoadConfigsAsync)}: Array is empty."); - - var results = await _configResourceParser.TryParseResourcesAsync(configResources); - var ret = new FluentResults.Result(); - - foreach (var result in results) - { - if (result.Errors.Any()) - ret.Errors.AddRange(result.Errors); - if (result.IsFailed || result.Value is not { Count: > 0 } res) - continue; - - foreach (var configInfo in res) - { - if (_configs.ContainsKey((configInfo.OwnerPackage, configInfo.InternalName))) - { - ret.Errors.Add(new Error($"{nameof(LoadConfigsAsync)}: Config already exists for the compound key {configInfo.OwnerPackage.Name} | {configInfo.InternalName}")); - continue; - } - - if (!_configTypeInitializers.TryGetValue(configInfo.DataType, out var initializer)) - { - ret.Errors.Add(new Error($"{nameof(LoadConfigsAsync)} No type initializer for {configInfo.DataType}")); - continue; - } - - - - var cfg = initializer(configInfo); - if (cfg.Errors.Any()) - ret.Errors.AddRange(cfg.Errors); - if (cfg.IsFailed || cfg.Value is not {} val) - continue; - - AddConfigInstance((configInfo.OwnerPackage, configInfo.InternalName), val); - } - } - - return ret; + throw new NotImplementedException(); } public async Task LoadConfigsProfilesAsync(ImmutableArray configProfileResources) { - using var lck = await _disposeOpsLock.AcquireReaderLock(); - _base.CheckDisposed(); - - if (configProfileResources.IsDefaultOrEmpty) - return FluentResults.Result.Fail($"{nameof(LoadConfigsProfilesAsync)}: Array is empty."); - - var results = await _configProfileResourceParser.TryParseResourcesAsync(configProfileResources); - var ret = new FluentResults.Result(); - - foreach (var result in results) - { - if (result.Errors.Any()) - ret.Errors.AddRange(result.Errors); - if (result.IsFailed || result.Value is not { Count: > 0 } res) - continue; - - foreach (var profileInfo in res) - { - if (_configProfiles.ContainsKey((profileInfo.OwnerPackage, profileInfo.InternalName))) - { - ret.Errors.Add(new Error($"{nameof(LoadConfigsProfilesAsync)}: Config already exists for the compound key {profileInfo.OwnerPackage.Name} | {profileInfo.InternalName}")); - continue; - } - - AddProfileInstance((profileInfo.OwnerPackage, profileInfo.InternalName), profileInfo); - } - } - - return ret; + throw new NotImplementedException(); } - public FluentResults.Result AddConfig(IConfigInfo configInfo) where TConfig : IConfigBase + public Result AddConfig(IConfigInfo configInfo) where TConfig : IConfigBase { - using var lck = _disposeOpsLock.AcquireReaderLock().GetAwaiter().GetResult(); - _base.CheckDisposed(); - - if (configInfo is null) - return FluentResults.Result.Fail($"{nameof(AddConfig)}: Config is null."); - - if (!_configTypeInitializers.TryGetValue(configInfo.DataType, out var initializer)) - return FluentResults.Result.Fail($"{nameof(AddConfig)}: No type initializer for {configInfo.DataType}"); - - var errList = new List(); - - try - { - var cfg = initializer(configInfo); - if (cfg.Errors.Any()) - errList.AddRange(cfg.Errors); - if (cfg.IsFailed || cfg.Value is null) - return FluentResults.Result.Fail($"Failed to initialize {configInfo.DataType}").WithErrors(errList); - AddConfigInstance((configInfo.OwnerPackage, configInfo.InternalName), cfg.Value); - return (TConfig)cfg.Value; - } - catch(Exception ex) - { - return FluentResults.Result.Fail($"Failed to initialize {configInfo.DataType}").WithError(new ExceptionalError(ex)); - } + throw new NotImplementedException(); } public FluentResults.Result ApplyProfileSettings(ContentPackage package, string profileName) { - using var lck = _disposeOpsLock.AcquireReaderLock().GetAwaiter().GetResult(); - _base.CheckDisposed(); - - if (package == null || string.IsNullOrEmpty(profileName)) - return FluentResults.Result.Fail($"{nameof(ApplyProfileSettings)}: ContentPackage and/or name were null or empty."); - - if (!_configProfiles.TryGetValue((package, profileName), out var list)) - return FluentResults.Result.Fail($"No profiles found for package {package.Name} with name {profileName}"); - - if (list.IsDefaultOrEmpty) - return FluentResults.Result.Fail($"{nameof(ApplyProfileSettings)}: No stored values for profile {profileName}."); - - var errList = new List(); - - foreach (var profileVal in list) - { - if (!_configs.TryGetValue((package, profileVal.ConfigName), out var val)) - continue; - - if (!val.TrySetValue(profileVal.Value)) - errList.Add(new Error($"Failed to apply value from profile named {profileName} to {val.InternalName}")); - // continue - } - - return FluentResults.Result.Ok().WithErrors(errList); + throw new NotImplementedException(); } public FluentResults.Result DisposePackageData(ContentPackage package) { - // stop regular ops during deletion ops - using var lck = _disposeOpsLock.AcquireWriterLock().GetAwaiter().GetResult(); - _base.CheckDisposed(); - - if (package is null) - return FluentResults.Result.Fail($"{nameof(DisposePackageData)}: Package was null."); + throw new NotImplementedException(); + } - var errList = new List(); - - if (_packageConfigReverseLookup.Remove(package, out var cfgKeys)) - { - if (cfgKeys.Any()) - { - foreach (var key in cfgKeys) - { - try - { - _configs.Remove(key, out var cfg); - cfg?.Dispose(); - } - catch (Exception e) - { - errList.Add(new ExceptionalError(e)); - } - } - } - } - - if (_packageProfilesReverseLookup.Remove(package, out var profileKeys)) - { - if (profileKeys.Any()) - { - foreach (var key in profileKeys) - { - _configProfiles.Remove(key, out _); - } - } - } - - _packageNameMap.Remove(package.Name, out _); - - return FluentResults.Result.Ok().WithErrors(errList); + public FluentResults.Result DisposeAllPackageData() + { + throw new NotImplementedException(); } public Result> GetConfigsForPackage(ContentPackage package) { - using var lck = _disposeOpsLock.AcquireReaderLock().GetAwaiter().GetResult(); - _base.CheckDisposed(); - - if (!_packageConfigReverseLookup.TryGetValue(package, out var keys) || keys.IsEmpty) - return FluentResults.Result.Fail($"No configs found for package {package.Name}"); - - return _configs.Where(kvp => keys.Contains(kvp.Key)).ToFrozenDictionary(kvp => kvp.Key, kvp => kvp.Value); + throw new NotImplementedException(); } public Result Value)>>> GetProfilesForPackage(ContentPackage package) { - using var lck = _disposeOpsLock.AcquireReaderLock().GetAwaiter().GetResult(); - _base.CheckDisposed(); - - if (!_packageProfilesReverseLookup.TryGetValue(package, out var keys) || keys.IsEmpty) - return FluentResults.Result.Fail($"No profiles found for package {package.Name}"); - - return _configProfiles.Where(kvp => keys.Contains(kvp.Key)).ToFrozenDictionary(kvp => kvp.Key, kvp => kvp.Value); + throw new NotImplementedException(); } public IReadOnlyDictionary<(ContentPackage Package, string Name), IConfigBase> GetAllConfigs() { - using var lck = _disposeOpsLock.AcquireReaderLock().GetAwaiter().GetResult(); - _base.CheckDisposed(); - - return _configs.ToFrozenDictionary(kvp => kvp.Key, kvp => kvp.Value); + throw new NotImplementedException(); } public bool TryGetConfig(ContentPackage package, string name, out T config) where T : IConfigBase { - using var lck = _disposeOpsLock.AcquireReaderLock().GetAwaiter().GetResult(); - _base.CheckDisposed(); - - config = default; - if (!_configs.TryGetValue((package, name), out var value)) - return false; - try - { - config = (T)value; - return true; - } - catch - { - return false; - } + throw new NotImplementedException(); } public async Task SaveAllConfigs() { - using var lck = await _disposeOpsLock.AcquireReaderLock(); - _base.CheckDisposed(); - if (_configs.IsEmpty) - return FluentResults.Result.Ok(); - var toSave = _configs.Where(kvp => kvp.Value is not null).Select(kvp => kvp.Value) - .ToImmutableArray(); - var errList = ImmutableArray.CreateBuilder(); - foreach (var config in toSave) - { - var res = await SaveConfigInternal(config); - if (res.Errors.Any()) - errList.AddRange(res.Errors); - } - return FluentResults.Result.Ok().WithErrors(errList.MoveToImmutable()); + throw new NotImplementedException(); } public async Task SaveConfigsForPackage(ContentPackage package) { - if (package is null) - return FluentResults.Result.Fail($"{nameof(SaveConfigsForPackage)}: Package was null."); - using var lck = await _disposeOpsLock.AcquireReaderLock(); - _base.CheckDisposed(); - if (!_packageConfigReverseLookup.TryGetValue(package, out var keys) || keys.IsEmpty) - return FluentResults.Result.Fail($"No configs found for package {package.Name}"); - ConcurrentQueue toSave = new(); - foreach (var key in keys) - { - if (_configs.TryGetValue(key, out var config)) - toSave.Enqueue(config); - } - if (toSave.IsEmpty) - return FluentResults.Result.Fail($"No configs found for package {package.Name}"); - var errList = ImmutableArray.CreateBuilder(); - while (toSave.TryDequeue(out var config)) - { - var res = await SaveConfigInternal(config); - if (res.Errors.Any()) - errList.AddRange(res.Errors); - } - return FluentResults.Result.Ok().WithErrors(errList.MoveToImmutable()); + throw new NotImplementedException(); } public async Task SaveConfig((ContentPackage Package, string ConfigName) config) { - if (config.Package is null || config.ConfigName.IsNullOrWhiteSpace()) - return FluentResults.Result.Fail($"{nameof(SaveConfig)}: Config properties were null or empty."); - using var lck = await _disposeOpsLock.AcquireReaderLock(); - _base.CheckDisposed(); - if (!_configs.TryGetValue(config, out var instance)) - return FluentResults.Result.Fail($"{nameof(SaveConfig)}: No config found for package {config.Package.Name} and name {config.ConfigName}"); - return await SaveConfigInternal(instance); + throw new NotImplementedException(); } - - private void SaveConfigEvent(IConfigBase instance) - { - using var lck = _disposeOpsLock.AcquireWriterLock().GetAwaiter().GetResult(); - _base.CheckDisposed(); - SaveConfigInternal(instance).GetAwaiter().GetResult(); - } - - private async Task SaveConfigInternal(IConfigBase instance) - { - var localStorePath = Path.Combine("Config", SanitizedFileName($"{instance.OwnerPackage.Name}.xml)")); - // Locking and checks must be handled by the caller. - var val = instance.GetSerializableValue(); - var docRes = await _storageService.Value.LoadLocalXmlAsync(instance.OwnerPackage, localStorePath); - XDocument doc; - XElement cfgElement; - XElement valueElement; - - // structure is - /* - * - * <[instance.InternalName]> - * - * <--Contents Here-> - * - * - * - */ - - if (docRes.IsFailed || docRes.Value is null) - { - doc = new XDocument( - new XElement("Config", new XAttribute("ContentPackage", instance.OwnerPackage.Name), - cfgElement = new XElement(instance.InternalName, valueElement = new XElement("Value")))); - } - else - { - doc = docRes.Value; - var e1 = doc.GetChildElement("Config"); - if (e1 is null) - { - e1 = new XElement("Config"); - doc.Add(e1); - } - - cfgElement = e1.GetChildElement(instance.InternalName); - if (cfgElement is null) - { - cfgElement = new XElement(instance.InternalName); - e1.Add(cfgElement); - } - - valueElement = cfgElement.GetChildElement("Value"); - if (valueElement is null) - { - valueElement = new XElement("Value"); - cfgElement.Add(valueElement); - } - } - - valueElement.Remove(); // remove from cfg - - // get potential updated element - var updatedElement = val.Match(str => - { - valueElement.RemoveAll(); - valueElement.Value = str; - return valueElement; - }, element => - { - valueElement.RemoveAll(); - valueElement.Add(element); - return valueElement; - }); - - // (re) add updated element. - cfgElement.Add(updatedElement); - - return await _storageService.Value.SaveLocalXmlAsync(instance.OwnerPackage, localStorePath, doc); - } - - private static readonly Regex RemoveInvalidChars = new Regex($"[{Regex.Escape(new string(System.IO.Path.GetInvalidFileNameChars()))}]", - RegexOptions.Singleline | RegexOptions.Compiled | RegexOptions.CultureInvariant); - - private string SanitizedFileName(string fileName, string replacement = "_") - { - return RemoveInvalidChars.Replace(fileName, replacement); - } - - } diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/LuaScriptManagementService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/LuaScriptManagementService.cs index 5d8d020e7..17b2c13c1 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/LuaScriptManagementService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/LuaScriptManagementService.cs @@ -116,8 +116,10 @@ class LuaScriptManagementService : ILuaScriptManagementService, ILuaDataService _script.Globals["CLIENT"] = LuaCsSetup.IsClient; } - public FluentResults.Result ExecuteLoadedScripts() + public FluentResults.Result ExecuteLoadedScripts(ImmutableArray executionOrder) { + throw new NotImplementedException($"Need to implement {nameof(executionOrder)} logic."); + if (_isRunning) { return FluentResults.Result.Fail("Tried to execute Lua scripts without unloading first."); diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PackageManagementService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PackageManagementService.cs index 802b2dc07..f8f92afaf 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PackageManagementService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PackageManagementService.cs @@ -1,9 +1,12 @@ -using System.Collections.Concurrent; +using System; +using System.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; +using System.Linq; using System.Threading.Tasks; using Barotrauma.LuaCs.Data; using FluentResults; +using Microsoft.Toolkit.Diagnostics; namespace Barotrauma.LuaCs.Services; @@ -12,20 +15,37 @@ public sealed class PackageManagementService : IPackageManagementService // svc private ILoggerService _logger; private IModConfigService _modConfigService; + private IConfigService _configService; private ILuaScriptManagementService _luaScriptManagementService; private IPluginManagementService _pluginManagementService; + private IPackageManagementServiceConfig _runConfig; // state private readonly ConcurrentDictionary _loadedPackages = new(); private readonly ConcurrentDictionary _runningPackages = new(); // control + /// + /// Service Disposal Lock. + /// private readonly AsyncReaderWriterLock _operationsLock = new(); + /// + /// Execution of packages lock. + ///
Read: Package loading/unloading (Multi-operation mode). + ///
Write: Package execution (exclusive mode). + ///
+ private readonly AsyncReaderWriterLock _executionLock = new(); - public PackageManagementService(ILoggerService logger, IModConfigService modConfigService, ILuaScriptManagementService luaScriptManagementService, IPluginManagementService pluginManagementService) + public PackageManagementService(ILoggerService logger, + IModConfigService modConfigService, + ILuaScriptManagementService luaScriptManagementService, + IPluginManagementService pluginManagementService, + IConfigService configService, IPackageManagementServiceConfig runConfig) { _logger = logger; _modConfigService = modConfigService; _luaScriptManagementService = luaScriptManagementService; _pluginManagementService = pluginManagementService; + _configService = configService; + _runConfig = runConfig; } public void Dispose() @@ -34,7 +54,7 @@ public sealed class PackageManagementService : IPackageManagementService if (!ModUtils.Threading.CheckIfClearAndSetBool(ref _isDisposed)) return; - _logger.LogMessage($"{nameof(PackageManagementService)} is disposing"); + _logger.LogMessage($"{nameof(PackageManagementService)} is disposing."); _luaScriptManagementService.Dispose(); _pluginManagementService.Dispose(); _modConfigService.Dispose(); @@ -61,79 +81,215 @@ public sealed class PackageManagementService : IPackageManagementService if (IsDisposed) return FluentResults.Result.Fail($"{nameof(PackageManagementService)}failed to reset. Has already been disposed."); - var operationResult = new FluentResults.Result(); - CombineResultErrors(operationResult, UnsafeStopRunningPackagesInternal()); - CombineResultErrors(operationResult, UnsafeUnloadAllPackagesInternal()); - return operationResult; - - void CombineResultErrors(FluentResults.Result result, - ImmutableArray<(ContentPackage Package, FluentResults.Result OperationResult)> packRes) + try { - if (packRes.IsDefaultOrEmpty) - return; - - foreach (var r in packRes) - { - if (r.OperationResult.IsSuccess) - continue; - _logger.LogResults(r.OperationResult); - result.WithErrors(r.OperationResult.Errors); - } + var operationResult = new FluentResults.Result(); + operationResult.WithReasons(_configService.Reset().Reasons); + operationResult.WithReasons(_luaScriptManagementService.Reset().Reasons); + operationResult.WithReasons(_pluginManagementService.Reset().Reasons); + _runningPackages.Clear(); + _loadedPackages.Clear(); + return operationResult; + } + catch (Exception e) + { + return FluentResults.Result.Fail(new ExceptionalError(e)); } } public FluentResults.Result LoadPackageInfo(ContentPackage package) { - throw new System.NotImplementedException(); + Guard.IsNotNull(package, nameof(package)); + using var lck = _operationsLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult(); + using var executeLock = _executionLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult(); + + IService.CheckDisposed(this); + if (_loadedPackages.TryGetValue(package, out var result)) + { + _logger.LogWarning($"{nameof(LoadPackageInfo)}: Tried to load already-loaded package {package.Name}."); + return FluentResults.Result.Ok(); + } + + var pkgCfgInfo = _modConfigService.CreateConfigAsync(package).ConfigureAwait(false).GetAwaiter().GetResult(); + if (pkgCfgInfo.IsFailed) + { + _logger.LogResults(pkgCfgInfo.ToResult()); + return pkgCfgInfo.ToResult(); + } + return UnsafeAddPackageInternal(package, pkgCfgInfo.Value); } - public ImmutableArray<(ContentPackage Package, FluentResults.Result LoadSuccessResult)> LoadPackagesInfo(IReadOnlyCollection packages) + public FluentResults.Result LoadPackagesInfo(ImmutableArray packages) { - throw new System.NotImplementedException(); + if (packages.IsDefaultOrEmpty) + ThrowHelper.ThrowArgumentException($"{nameof(LoadPackagesInfo)}: packages list is empty."); + using var lck = _operationsLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult(); + using var executeLock = _executionLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult(); + + IService.CheckDisposed(this); + var result = new FluentResults.Result(); + var pkgConfigs = _modConfigService.CreateConfigsAsync([..packages]).ConfigureAwait(false).GetAwaiter().GetResult(); + foreach (var pkgConfig in pkgConfigs) + { + result.WithReasons(pkgConfig.Config.Reasons); + if (pkgConfig.Config.IsSuccess) + result.WithReasons(UnsafeAddPackageInternal(pkgConfig.Source, pkgConfig.Config.Value).Reasons); + } + + return result; } - private FluentResults.Result UnsafeLoadPackageInfoInternal(ContentPackage package) + private FluentResults.Result UnsafeAddPackageInternal(ContentPackage package, IModConfigInfo config) { - throw new System.NotImplementedException(); + if (_loadedPackages.TryGetValue(package, out var result)) + { + _logger.LogWarning($"Tried to load already-loaded package {package.Name}."); + return FluentResults.Result.Ok(); + } + + _loadedPackages[package] = config; + var res = new FluentResults.Result(); + res.WithReasons(_luaScriptManagementService.LoadScriptResourcesAsync(config.LuaScripts).ConfigureAwait(false).GetAwaiter().GetResult().Reasons); + return res; } - public ImmutableArray<(ContentPackage Package, FluentResults.Result ExecutionResult)> ExecuteLoadedPackages() + public FluentResults.Result ExecuteLoadedPackages(ImmutableArray executionOrder) { - throw new System.NotImplementedException(); - } + using var lck = _operationsLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult(); + using var executeLock = _executionLock.AcquireWriterLock().ConfigureAwait(false).GetAwaiter().GetResult(); + IService.CheckDisposed(this); - private ImmutableArray<(ContentPackage Package, FluentResults.Result StopExectionResult)> UnsafeStopRunningPackagesInternal() - { - throw new System.NotImplementedException(); + if (executionOrder.IsDefaultOrEmpty) + return FluentResults.Result.Fail($"{nameof(ExecuteLoadedPackages)}: No packages in the execution order list."); + + if (!_runningPackages.IsEmpty) + { + return FluentResults.Result.Fail( + $"{nameof(ExecuteLoadedPackages)}: There are already packages running! List: { + _runningPackages.Aggregate(string.Empty, (acc, kvp) => "-" + kvp + "\n" + kvp.Key.Name)}"); + } + + if (_loadedPackages.IsEmpty) + return FluentResults.Result.Fail($"{nameof(ExecuteLoadedPackages)}: No packages loaded. Nothing to run!)"); + + var result = new FluentResults.Result(); + + // get loading order. Note: packages not in the execution order list will load first. + var loadingOrderedPackages = _loadedPackages.OrderBy(pkg => executionOrder.IndexOf(pkg.Key)) + .ToImmutableArray(); + + //mod settings + var settings = loadingOrderedPackages + .SelectMany(pkg => pkg.Value.Configs.OrderBy(scr => scr.LoadPriority)) + .ToImmutableArray(); + if (!settings.IsDefaultOrEmpty) + { + result.WithReasons(_configService.LoadConfigsAsync(settings).ConfigureAwait(false).GetAwaiter() + .GetResult().Reasons); + result.WithReasons(_configService.LoadConfigsProfilesAsync(settings).ConfigureAwait(false) + .GetAwaiter().GetResult().Reasons); + } + + //lua scripts + var luaScripts = loadingOrderedPackages + .SelectMany(pkg => pkg.Value.LuaScripts.OrderBy(scr => scr.LoadPriority)) + .ToImmutableArray(); + if (!luaScripts.IsDefaultOrEmpty) + result.WithReasons(_luaScriptManagementService.ExecuteLoadedScripts(luaScripts).Reasons); + + if (_runConfig.IsCsEnabled) + { + var plugins = + loadingOrderedPackages.SelectMany(pkg => pkg.Value.Assemblies.OrderBy(scr => scr.LoadPriority)) + .ToImmutableArray(); + if (!plugins.IsDefaultOrEmpty) + result.WithReasons(_pluginManagementService.LoadAssemblyResources(plugins).Reasons); + } + + return result; } - public ImmutableArray<(ContentPackage Package, FluentResults.Result StopExecutionResult)> StopRunningPackages() + public FluentResults.Result StopRunningPackages() { - throw new System.NotImplementedException(); - } - - private FluentResults.Result UnsafeUnloadPackageInternal(ContentPackage package) - { - throw new System.NotImplementedException(); - } - - private ImmutableArray<(ContentPackage Package, FluentResults.Result UnloadSuccessResult)> UnsafeUnloadAllPackagesInternal() - { - throw new System.NotImplementedException(); + using var lck = _operationsLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult(); + using var executeLock = _executionLock.AcquireWriterLock().ConfigureAwait(false).GetAwaiter().GetResult(); + IService.CheckDisposed(this); + + if (_loadedPackages.IsEmpty || _runningPackages.IsEmpty) + { + _logger.LogWarning($"{nameof(StopRunningPackages)}: No packages are currently executing."); + return FluentResults.Result.Ok(); + } + + var res = new FluentResults.Result(); + res.WithReasons(_luaScriptManagementService.UnloadActiveScripts().Reasons); + res.WithReasons(_pluginManagementService.UnloadManagedAssemblies().Reasons); + _runningPackages.Clear(); + return res; } public FluentResults.Result UnloadPackage(ContentPackage package) { - throw new System.NotImplementedException(); + Guard.IsNotNull(package, nameof(package)); + using var lck = _operationsLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult(); + using var executeLock = _executionLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult(); + IService.CheckDisposed(this); + + if (!_loadedPackages.ContainsKey(package)) + return FluentResults.Result.Fail($"{nameof(UnloadPackage)}: The package is not loaded."); + if (!_runningPackages.IsEmpty) + return FluentResults.Result.Fail($"{nameof(UnloadPackage)}: Packages are currently executing."); + var result = new FluentResults.Result(); + result.WithReasons(_luaScriptManagementService.DisposePackageResources(package).Reasons); + result.WithReasons(_configService.DisposePackageData(package).Reasons); + _loadedPackages.TryRemove(package, out _); + return result; } - public ImmutableArray<(ContentPackage Package, FluentResults.Result UnloadSuccessResult)> UnloadPackages(IReadOnlyCollection packages) + public FluentResults.Result UnloadPackages(ImmutableArray packages) { - throw new System.NotImplementedException(); + if (packages.IsDefaultOrEmpty) + return FluentResults.Result.Fail($"{nameof(UnloadPackages)}: Package list is empty."); + + using var lck = _operationsLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult(); + using var executeLock = _executionLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult(); + IService.CheckDisposed(this); + + var result = new FluentResults.Result(); + foreach (var package in packages) + result.WithReasons(UnloadPackage(package).Reasons); + return result; } - public ImmutableArray<(ContentPackage Package, FluentResults.Result UnloadSuccessResult)> UnloadAllPackages() + public FluentResults.Result UnloadAllPackages() { - throw new System.NotImplementedException(); + using var lck = _operationsLock.AcquireWriterLock().ConfigureAwait(false).GetAwaiter().GetResult(); + using var executeLock = _executionLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult(); + IService.CheckDisposed(this); + + if (_loadedPackages.IsEmpty) + return FluentResults.Result.Ok(); + if (!_runningPackages.IsEmpty) + return FluentResults.Result.Fail($"{nameof(UnloadAllPackages)}: Packages are currently executing."); + var result = new FluentResults.Result(); + result.WithReasons(_luaScriptManagementService.DisposeAllPackageResources().Reasons); + result.WithReasons(_configService.DisposeAllPackageData().Reasons); + _loadedPackages.Clear(); + return result; + } + + public ImmutableArray GetAllLoadedPackages() + { + using var lck = _operationsLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult(); + IService.CheckDisposed(this); + return [.._loadedPackages.Keys]; + } + + public bool IsPackageRunning(ContentPackage package) + { + Guard.IsNotNull(package, nameof(package)); + using var lck = _operationsLock.AcquireReaderLock().ConfigureAwait(false).GetAwaiter().GetResult(); + IService.CheckDisposed(this); + return _runningPackages.ContainsKey(package); } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PluginManagementService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PluginManagementService.cs index 2138961e7..667447b3f 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PluginManagementService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PluginManagementService.cs @@ -128,7 +128,7 @@ public class PluginManagementService : IPluginManagementService, IAssemblyManage throw new NotImplementedException(); } - public IReadOnlyList> ActivateTypeInstances(ImmutableArray types, bool serviceInjection = true, + public ImmutableArray> ActivateTypeInstances(ImmutableArray types, bool serviceInjection = true, bool hostInstanceReference = false) where T : IDisposable { throw new NotImplementedException(); diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IConfigService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IConfigService.cs index f9f08d689..38498830b 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IConfigService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IConfigService.cs @@ -35,6 +35,7 @@ public partial interface IConfigService : IReusableService, ILuaConfigService // Utility FluentResults.Result ApplyProfileSettings(ContentPackage package, string profileName); FluentResults.Result DisposePackageData(ContentPackage package); + FluentResults.Result DisposeAllPackageData(); FluentResults.Result> GetConfigsForPackage(ContentPackage package); FluentResults.Result Value)>>> GetProfilesForPackage(ContentPackage package); diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/ILuaScriptManagementService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/ILuaScriptManagementService.cs index 74be9298f..4ca8ea401 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/ILuaScriptManagementService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/ILuaScriptManagementService.cs @@ -27,11 +27,12 @@ public interface ILuaScriptManagementService : IReusableService Task LoadScriptResourcesAsync(ImmutableArray resourcesInfo); /// - /// + /// Executes already loaded into memory scripts data, in the supplied order. /// + /// /// // [Required] - FluentResults.Result ExecuteLoadedScripts(); + FluentResults.Result ExecuteLoadedScripts(ImmutableArray executionOrder); /// /// diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IPackageManagementService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IPackageManagementService.cs index 3f0614154..3979ce69d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IPackageManagementService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IPackageManagementService.cs @@ -12,10 +12,12 @@ namespace Barotrauma.LuaCs.Services; public interface IPackageManagementService : IReusableService { public FluentResults.Result LoadPackageInfo(ContentPackage package); - public ImmutableArray<(ContentPackage Package, FluentResults.Result LoadSuccessResult)> LoadPackagesInfo(IReadOnlyCollection packages); - public ImmutableArray<(ContentPackage Package, FluentResults.Result ExecutionResult)> ExecuteLoadedPackages(); - public ImmutableArray<(ContentPackage Package, FluentResults.Result StopExecutionResult)> StopRunningPackages(); - public FluentResults.Result UnloadPackage(ContentPackage package); - public ImmutableArray<(ContentPackage Package, FluentResults.Result UnloadSuccessResult)> UnloadPackages(IReadOnlyCollection packages); - public ImmutableArray<(ContentPackage Package, FluentResults.Result UnloadSuccessResult)> UnloadAllPackages(); + public FluentResults.Result LoadPackagesInfo(ImmutableArray packages); + public FluentResults.Result ExecuteLoadedPackages(ImmutableArray executionOrder); + public FluentResults.Result StopRunningPackages(); + public FluentResults.Result UnloadPackage(ContentPackage package); + public FluentResults.Result UnloadPackages(ImmutableArray packages); + public FluentResults.Result UnloadAllPackages(); + public ImmutableArray GetAllLoadedPackages(); + public bool IsPackageRunning(ContentPackage package); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IPluginManagementService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IPluginManagementService.cs index dbb87bdf9..57648ccd1 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IPluginManagementService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IPluginManagementService.cs @@ -47,12 +47,13 @@ public interface IPluginManagementService : IReusableService /// /// /// - IReadOnlyList> ActivateTypeInstances(ImmutableArray types, bool serviceInjection = true, + ImmutableArray> ActivateTypeInstances(ImmutableArray types, bool serviceInjection = true, bool hostInstanceReference = false) where T : IDisposable; + /// /// Unloads all managed , , and s. /// - /// Success of the operation.
Note: does not guarantee .NET runtime assembly unloading success.
+ /// Success of the operation.
Note: does not guarantee .NET runtime assembly unloading success.
FluentResults.Result UnloadManagedAssemblies(); }