From 6e66a3114a864a883eb4122e2ea5d0d76f8d3313 Mon Sep 17 00:00:00 2001 From: MapleWheels Date: Fri, 23 Jan 2026 13:48:01 -0500 Subject: [PATCH] - Made Package loading conditional on resources being available. - Made States registration use named parameters. - Changed IPluginManagementService interface to better suit expected return results. --- .../ClientSource/LuaCs/LuaCsSettingsMenu.cs | 20 ++-- .../ClientSource/LuaCs/LuaCsSetup.cs | 8 +- .../Characters/CharacterNetworking.cs | 2 +- .../LuaCs/Lua/LuaClasses/LuaCsUtility.cs | 2 +- .../SharedSource/LuaCs/LuaCsSetup.cs | 105 ++++++++++++------ .../Services/PackageManagementService.cs | 51 +++++---- .../LuaCs/Services/PluginManagementService.cs | 20 +++- .../_Interfaces/IPluginManagementService.cs | 2 +- .../SharedSource/LuaCs/StateMachine.cs | 2 +- 9 files changed, 136 insertions(+), 76 deletions(-) diff --git a/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSettingsMenu.cs b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSettingsMenu.cs index f1e5985bb..b6408d2a4 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSettingsMenu.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSettingsMenu.cs @@ -19,55 +19,55 @@ namespace Barotrauma new GUITickBox(new RectTransform(new Vector2(0.8f, 0.1f), list.Content.RectTransform), "Enable CSharp Scripting") { - Selected = GameMain.LuaCs.IsCsEnabled?.Value ?? false, + Selected = GameMain.LuaCs.IsCsEnabled, ToolTip = "This enables CSharp Scripting for mods to use, WARNING: CSharp is NOT sandboxed, be careful with what mods you download.", OnSelected = (GUITickBox tick) => { - GameMain.LuaCs.IsCsEnabled?.TrySetValue(tick.Selected); + GameMain.LuaCs.IsCsEnabled = tick.Selected; return true; } }; new GUITickBox(new RectTransform(new Vector2(0.8f, 0.1f), list.Content.RectTransform), "Treat Forced Mods As Normal") { - Selected = GameMain.LuaCs.TreatForcedModsAsNormal?.Value ?? false, + Selected = GameMain.LuaCs.TreatForcedModsAsNormal, ToolTip = "This makes mods that were setup to run even when disabled to only run when enabled.", OnSelected = (GUITickBox tick) => { - GameMain.LuaCs.TreatForcedModsAsNormal?.TrySetValue(tick.Selected); + GameMain.LuaCs.TreatForcedModsAsNormal = tick.Selected; return true; } }; new GUITickBox(new RectTransform(new Vector2(0.8f, 0.1f), list.Content.RectTransform), "Prefer To Use Workshop Lua Setup") { - Selected = GameMain.LuaCs.PreferToUseWorkshopLuaSetup?.Value ?? false, + Selected = GameMain.LuaCs.PreferToUseWorkshopLuaSetup, ToolTip = "This makes Lua look first for the Lua/LuaSetup.lua located in the Workshop package instead of the one located locally.", OnSelected = (GUITickBox tick) => { - GameMain.LuaCs.PreferToUseWorkshopLuaSetup?.TrySetValue(tick.Selected); + GameMain.LuaCs.PreferToUseWorkshopLuaSetup = tick.Selected; return true; } }; new GUITickBox(new RectTransform(new Vector2(0.8f, 0.1f), list.Content.RectTransform), "Disable Error GUI Overlay") { - Selected = GameMain.LuaCs.DisableErrorGUIOverlay?.Value ?? false, + Selected = GameMain.LuaCs.DisableErrorGUIOverlay, ToolTip = "", OnSelected = (GUITickBox tick) => { - GameMain.LuaCs.DisableErrorGUIOverlay?.TrySetValue(tick.Selected); + GameMain.LuaCs.DisableErrorGUIOverlay = tick.Selected; return true; } }; new GUITickBox(new RectTransform(new Vector2(0.8f, 0.1f), list.Content.RectTransform), "Hide usernames In Error Logs") { - Selected = GameMain.LuaCs.HideUserNamesInLogs?.Value ?? false, + Selected = GameMain.LuaCs.HideUserNamesInLogs, ToolTip = "Hides the operating system username when displaying error logs (eg your username on windows).", OnSelected = (GUITickBox tick) => { - GameMain.LuaCs.HideUserNamesInLogs?.TrySetValue(tick.Selected); + GameMain.LuaCs.HideUserNamesInLogs = tick.Selected; return true; } }; diff --git a/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSetup.cs b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSetup.cs index 4a30e21f4..35dafe4e2 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSetup.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSetup.cs @@ -15,7 +15,7 @@ namespace Barotrauma { public void AddToGUIUpdateList() { - if (!DisableErrorGUIOverlay.Value) + if (!DisableErrorGUIOverlay) { LuaCsLogger.AddToGUIUpdateList(); } @@ -28,7 +28,7 @@ namespace Barotrauma public bool CheckCsEnabled() { // fast exit if enabled or unavailable. - if (this.IsCsEnabled?.Value ?? true ) + if (this.IsCsEnabled) { return false; } @@ -60,14 +60,14 @@ namespace Barotrauma msg.Buttons[0].OnClicked = (GUIButton button, object obj) => { - this.IsCsEnabled.TrySetValue(true); + this.IsCsEnabled = true; isCsValueChanged = true; return true; }; msg.Buttons[1].OnClicked = (GUIButton button, object obj) => { - this.IsCsEnabled.TrySetValue(false); + this.IsCsEnabled = false; return true; }; diff --git a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs index ea7816fba..560dd223e 100644 --- a/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs +++ b/Barotrauma/BarotraumaServer/ServerSource/Characters/CharacterNetworking.cs @@ -815,7 +815,7 @@ namespace Barotrauma var tempBuffer = new ReadWriteMessage(); WriteStatus(tempBuffer, forceAfflictionData: true); - if (msgLengthBeforeStatus + tempBuffer.LengthBytes >= 255 && restrictMessageSize && (GameMain.LuaCs.RestrictMessageSize?.Value ?? false)) + if (msgLengthBeforeStatus + tempBuffer.LengthBytes >= 255 && restrictMessageSize && (GameMain.LuaCs.RestrictMessageSize)) { msg.WriteBoolean(false); if (msgLengthBeforeStatus < 255) diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaClasses/LuaCsUtility.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaClasses/LuaCsUtility.cs index f801a23ef..fd797cfc7 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaClasses/LuaCsUtility.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Lua/LuaClasses/LuaCsUtility.cs @@ -60,7 +60,7 @@ namespace Barotrauma foreach (var package in ContentPackageManager.AllPackages) { - if (package.UgcId.ValueEquals(new SteamWorkshopId(GameMain.LuaCs.LuaForBarotraumaSteamId?.Value ?? 0ul)) + if (package.UgcId.ValueEquals(new SteamWorkshopId(GameMain.LuaCs.LuaForBarotraumaSteamId)) && pathStartsWith(getFullPath(package.Path))) { return false; diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs index 699543597..f19a3a5c2 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/LuaCsSetup.cs @@ -5,6 +5,7 @@ using System.Collections.Immutable; using System.IO; using System.Linq; using System.Net.Mime; +using System.Reflection; using System.Threading; using System.Threading.Tasks; using Barotrauma.LuaCs; @@ -93,60 +94,102 @@ namespace Barotrauma public LuaGame Game => _servicesProvider.GetService(); internal IStorageService StorageService => _servicesProvider.GetService(); - + /// /// Whether C# plugin code is enabled. /// - internal ISettingEntry IsCsEnabled { get; private set; } - + public bool IsCsEnabled + { + get => _isCsEnabled?.Value ?? false; + internal set => _isCsEnabled?.TrySetValue(value); + } + + private ISettingEntry _isCsEnabled; + /// /// Whether mods marked as 'forced' or 'always load' should only be loaded if they're in the enabled mods list. /// - internal ISettingEntry TreatForcedModsAsNormal { get; private set; } - + public bool TreatForcedModsAsNormal + { + get => _treatForcedModsAsNormal?.Value ?? true; + internal set => _treatForcedModsAsNormal?.TrySetValue(value); + } + + private ISettingEntry _treatForcedModsAsNormal; + /// /// Whether the lua script runner from Workshop package should be used over the in-built version. /// - internal ISettingEntry PreferToUseWorkshopLuaSetup { get; private set; } - + public bool PreferToUseWorkshopLuaSetup + { + get => _preferToUseWorkshopLuaSetup?.Value ?? false; + internal set => _preferToUseWorkshopLuaSetup?.TrySetValue(value); + } + private ISettingEntry _preferToUseWorkshopLuaSetup; + /// /// Whether the popup error GUI should be hidden/suppressed. /// - internal ISettingEntry DisableErrorGUIOverlay { get; private set; } - + public bool DisableErrorGUIOverlay + { + get => _disableErrorGUIOverlay?.Value ?? false; + internal set => _disableErrorGUIOverlay?.TrySetValue(value); + } + private ISettingEntry _disableErrorGUIOverlay; + /// /// Whether usernames are anonymized or show in logs. /// - internal ISettingEntry HideUserNamesInLogs { get; private set; } - + public bool HideUserNamesInLogs + { + get => _hideUserNamesInLogs?.Value ?? false; + internal set => _hideUserNamesInLogs?.TrySetValue(value); + } + private ISettingEntry _hideUserNamesInLogs; + /// /// The SteamId of the Workshop LuaCs CPackage in use, if available. /// - internal ISettingEntry LuaForBarotraumaSteamId { get; private set; } - + public ulong LuaForBarotraumaSteamId + { + get => _luaForBarotraumaSteamId?.Value ?? 0; + internal set => _luaForBarotraumaSteamId?.TrySetValue(value); + } + private ISettingEntry _luaForBarotraumaSteamId; + /// /// TODO: @evilfactory@users.noreply.github.com /// - internal ISettingEntry RestrictMessageSize { get; private set; } - + public bool RestrictMessageSize + { + get => _restrictMessageSize?.Value ?? false; + internal set => _restrictMessageSize?.TrySetValue(value); + } + private ISettingEntry _restrictMessageSize; + /// /// The local save path for all local data storage for mods. /// - internal ISettingEntry LocalDataSavePath { get; private set; } + public string LocalDataSavePath + { + get => _localDataSavePath?.Value ?? Path.Combine(Directory.GetCurrentDirectory(), "/Data/Mods"); + internal set => _localDataSavePath?.TrySetValue(value); + } + private ISettingEntry _localDataSavePath; void LoadLuaCsConfig() { - IsCsEnabled = ConfigService.TryGetConfig>(ContentPackageManager.VanillaCorePackage, "IsCsEnabled", out var val1) ? val1 + _isCsEnabled = ConfigService.TryGetConfig>(ContentPackageManager.VanillaCorePackage, "IsCsEnabled", out var val1) ? val1 : throw new NullReferenceException($"{nameof(IsCsEnabled)} cannot be loaded."); - TreatForcedModsAsNormal = ConfigService.TryGetConfig>(ContentPackageManager.VanillaCorePackage, "TreatForcedModsAsNormal", out var val2) ? val2 + _treatForcedModsAsNormal = ConfigService.TryGetConfig>(ContentPackageManager.VanillaCorePackage, "TreatForcedModsAsNormal", out var val2) ? val2 : throw new NullReferenceException($"{nameof(TreatForcedModsAsNormal)} cannot be loaded."); - DisableErrorGUIOverlay = ConfigService.TryGetConfig>(ContentPackageManager.VanillaCorePackage, "DisableErrorGUIOverlay", out var val3) ? val3 + _disableErrorGUIOverlay = ConfigService.TryGetConfig>(ContentPackageManager.VanillaCorePackage, "DisableErrorGUIOverlay", out var val3) ? val3 : throw new NullReferenceException($"{nameof(DisableErrorGUIOverlay)} cannot be loaded."); - HideUserNamesInLogs = ConfigService.TryGetConfig>(ContentPackageManager.VanillaCorePackage, "HideUserNamesInLogs", out var val4) ? val4 + _hideUserNamesInLogs = ConfigService.TryGetConfig>(ContentPackageManager.VanillaCorePackage, "HideUserNamesInLogs", out var val4) ? val4 : throw new NullReferenceException($"{nameof(HideUserNamesInLogs)} cannot be loaded."); - LuaForBarotraumaSteamId = ConfigService.TryGetConfig>(ContentPackageManager.VanillaCorePackage, "LuaForBarotraumaSteamId", out var val5) ? val5 + _luaForBarotraumaSteamId = ConfigService.TryGetConfig>(ContentPackageManager.VanillaCorePackage, "LuaForBarotraumaSteamId", out var val5) ? val5 : throw new NullReferenceException($"{nameof(LuaForBarotraumaSteamId)} cannot be loaded."); - RestrictMessageSize = ConfigService.TryGetConfig>(ContentPackageManager.VanillaCorePackage, "RestrictMessageSize", out var val7) ? val7 + _restrictMessageSize = ConfigService.TryGetConfig>(ContentPackageManager.VanillaCorePackage, "RestrictMessageSize", out var val7) ? val7 : throw new NullReferenceException($"{nameof(RestrictMessageSize)} cannot be loaded."); } @@ -244,9 +287,9 @@ namespace Barotrauma private StateMachine SetupStateMachine() { - return new StateMachine(false, RunState.Unloaded, RunStateUnloaded_OnEnter, null) - .AddState(RunState.LoadedNoExec, RunStateLoadedNoExec_OnEnter, null) - .AddState(RunState.Running, RunStateRunning_OnEnter, RunStateRunning_OnExit); + return new StateMachine(false, RunState.Unloaded, onEnter: RunStateUnloaded_OnEnter, null) + .AddState(RunState.LoadedNoExec, onEnter: RunStateLoadedNoExec_OnEnter, null) + .AddState(RunState.Running, onEnter: RunStateRunning_OnEnter, RunStateRunning_OnExit); // ReSharper disable InconsistentNaming void RunStateUnloaded_OnEnter(State currentState) @@ -355,12 +398,12 @@ namespace Barotrauma void DisposeLuaCsConfig() { - IsCsEnabled = null; - TreatForcedModsAsNormal = null; - DisableErrorGUIOverlay = null; - HideUserNamesInLogs = null; - LuaForBarotraumaSteamId = null; - RestrictMessageSize = null; + _isCsEnabled = null; + _treatForcedModsAsNormal = null; + _disableErrorGUIOverlay = null; + _hideUserNamesInLogs = null; + _luaForBarotraumaSteamId = null; + _restrictMessageSize = null; } } diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PackageManagementService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PackageManagementService.cs index 22a3626b6..a16ec5e50 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PackageManagementService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PackageManagementService.cs @@ -151,17 +151,28 @@ public sealed class PackageManagementService : IPackageManagementService try { var res = new FluentResults.Result(); - var configsTask = new Task>(async Task () => - new FluentResults.Result() - .WithReasons((await _configService.LoadConfigsAsync(config.Configs)).Reasons) - .WithReasons((await _configService.LoadConfigsProfilesAsync(config.Configs)).Reasons)); - var luaScriptsTask = new Task>(async () => - await _luaScriptManagementService.LoadScriptResourcesAsync(config.LuaScripts)); + var tasks = ImmutableArray.CreateBuilder>>(); + + if (!config.Configs.IsDefaultOrEmpty) + { + tasks.Add(Task.Factory.StartNew(async Task () => + new FluentResults.Result() + .WithReasons((await _configService.LoadConfigsAsync(config.Configs)).Reasons) + .WithReasons((await _configService.LoadConfigsProfilesAsync(config.Configs)).Reasons))); + } + + if (!config.LuaScripts.IsDefaultOrEmpty) + { + tasks.Add(Task.Factory.StartNew(async () => + await _luaScriptManagementService.LoadScriptResourcesAsync(config.LuaScripts))); + } + + if (tasks.Count == 0) + { + return FluentResults.Result.Ok(); + } - configsTask.Start(); - luaScriptsTask.Start(); - - var r = Task.WhenAll(configsTask, luaScriptsTask).ConfigureAwait(false).GetAwaiter().GetResult(); + var r = Task.WhenAll(tasks.ToArray()).ConfigureAwait(false).GetAwaiter().GetResult(); foreach (var task in r) res.WithReasons(task.ConfigureAwait(false).GetAwaiter().GetResult().Reasons); @@ -180,7 +191,9 @@ public sealed class PackageManagementService : IPackageManagementService IService.CheckDisposed(this); if (executionOrder.IsDefaultOrEmpty) + { return FluentResults.Result.Fail($"{nameof(ExecuteLoadedPackages)}: No packages in the execution order list."); + } if (!_runningPackages.IsEmpty) { @@ -190,7 +203,9 @@ public sealed class PackageManagementService : IPackageManagementService } if (_loadedPackages.IsEmpty) + { return FluentResults.Result.Fail($"{nameof(ExecuteLoadedPackages)}: No packages loaded. Nothing to run!)"); + } var result = new FluentResults.Result(); @@ -198,24 +213,16 @@ public sealed class PackageManagementService : IPackageManagementService 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); - } + // NOTE: Config/Settings are instanced in LoadPackages() //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) { @@ -223,7 +230,9 @@ public sealed class PackageManagementService : IPackageManagementService loadingOrderedPackages.SelectMany(pkg => pkg.Value.Assemblies.OrderBy(scr => scr.LoadPriority)) .ToImmutableArray(); if (!plugins.IsDefaultOrEmpty) + { result.WithReasons(_pluginManagementService.LoadAssemblyResources(plugins).Reasons); + } } return result; diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PluginManagementService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PluginManagementService.cs index 667447b3f..9cd47e486 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PluginManagementService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/PluginManagementService.cs @@ -13,6 +13,7 @@ using Barotrauma.LuaCs.Data; using Barotrauma.LuaCs.Events; using FluentResults; using FluentResults.LuaCs; +using ImpromptuInterface.Build; using Microsoft.CodeAnalysis; using OneOf; @@ -21,14 +22,15 @@ namespace Barotrauma.LuaCs.Services; public class PluginManagementService : IPluginManagementService, IAssemblyManagementService { private readonly Func _assemblyLoaderServiceFactory; - private readonly ConcurrentDictionary ResourceInfos, IAssemblyLoaderService Loader)> _packageAssemblyResources; - private readonly ConcurrentDictionary> _pluginInstances; + private readonly ConcurrentDictionary ResourceInfos, IAssemblyLoaderService Loader)> _packageAssemblyResources = new(); + private readonly ConcurrentDictionary> _pluginInstances = new(); private readonly Lazy _eventService; - private readonly ConditionalWeakTable _unloadingAssemblyLoaders; - private readonly ConditionalWeakTable> _assemblyTypesCache; + private readonly ConditionalWeakTable _unloadingAssemblyLoaders = new(); + private readonly ConditionalWeakTable> _assemblyTypesCache = new(); public PluginManagementService( - Func assemblyLoaderServiceFactory, + Func assemblyLoaderServiceFactory, Lazy eventService) { _assemblyLoaderServiceFactory = assemblyLoaderServiceFactory; @@ -123,14 +125,20 @@ public class PluginManagementService : IPluginManagementService, IAssemblyManage throw new NotImplementedException(); } - public Result> LoadAssemblyResources(ImmutableArray resource) + public FluentResults.Result LoadAssemblyResources(ImmutableArray resource) { +#if DEBUG + return FluentResults.Result.Fail($"{nameof(LoadAssemblyResources)}: Plugin loading not currently implemented."); +#endif throw new NotImplementedException(); } public ImmutableArray> ActivateTypeInstances(ImmutableArray types, bool serviceInjection = true, bool hostInstanceReference = false) where T : IDisposable { +#if DEBUG + return ImmutableArray>.Empty; +#endif throw new NotImplementedException(); } diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IPluginManagementService.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IPluginManagementService.cs index 57648ccd1..81ebe8f0d 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IPluginManagementService.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/Services/_Interfaces/IPluginManagementService.cs @@ -37,7 +37,7 @@ public interface IPluginManagementService : IReusableService /// /// /// Success/Failure and list of failed resources, if any. - FluentResults.Result> LoadAssemblyResources(ImmutableArray resource); + FluentResults.Result LoadAssemblyResources(ImmutableArray resource); /// /// Creates instances of the given type and provides Property Injection and instance reference caching. Disposes of diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/StateMachine.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/StateMachine.cs index 99f8ac1fe..809a2f9c1 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/StateMachine.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/StateMachine.cs @@ -30,7 +30,7 @@ public class StateMachine where T : Enum ThrowHelper.ThrowArgumentException($"State with id {stateId} already exists."); } - _states[stateId] = new State(stateId, onEnter, onExit); + _states[stateId] = new State(stateId, onEnterState: onEnter, onExitState: onExit); return this; }