From 94556fd6e707af4b3f4f7c19ecbd51b8383e094a Mon Sep 17 00:00:00 2001 From: MapleWheels Date: Wed, 25 Feb 2026 15:19:01 -0500 Subject: [PATCH] - SettingsMenuService added. - Added Settings Tab to vanilla SettingsMenu - Fixed ISystem implementation. --- .../ClientSource/LuaCs/LuaCsSetup.cs | 1 + .../LuaCs/Services/SettingsMenuSystem.cs | 94 +++++++++++++++++++ .../{ => _Interfaces}/IClientLoggerService.cs | 0 .../{ => _Interfaces}/IConfigService.cs | 0 .../_Interfaces/ISettingsMenuService.cs | 6 ++ .../{ => _Interfaces}/IUIStylesCollection.cs | 0 .../{ => _Interfaces}/IUIStylesService.cs | 0 .../Screens/MainMenuScreen/MainMenuScreen.cs | 4 +- .../ClientSource/Settings/SettingsMenu.cs | 32 +++---- .../LocalMods/LuaCsForBarotrauma/filelist.xml | 2 +- .../LuaCs/_Services/ServicesProvider.cs | 31 +++--- 11 files changed, 133 insertions(+), 37 deletions(-) create mode 100644 Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/SettingsMenuSystem.cs rename Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/{ => _Interfaces}/IClientLoggerService.cs (100%) rename Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/{ => _Interfaces}/IConfigService.cs (100%) create mode 100644 Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/_Interfaces/ISettingsMenuService.cs rename Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/{ => _Interfaces}/IUIStylesCollection.cs (100%) rename Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/{ => _Interfaces}/IUIStylesService.cs (100%) diff --git a/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSetup.cs b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSetup.cs index 31c633b81..96490b7ce 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSetup.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/LuaCsSetup.cs @@ -98,6 +98,7 @@ namespace Barotrauma //serviceProvider.RegisterServiceType(ServiceLifetime.Transient); serviceProvider.RegisterServiceType, ModConfigFileParserService>(ServiceLifetime.Transient); serviceProvider.RegisterServiceType(ServiceLifetime.Transient); + serviceProvider.RegisterServiceType(ServiceLifetime.Singleton); } /// diff --git a/Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/SettingsMenuSystem.cs b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/SettingsMenuSystem.cs new file mode 100644 index 000000000..e3cdf5f1e --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/SettingsMenuSystem.cs @@ -0,0 +1,94 @@ +using System; +using Barotrauma.Extensions; +using HarmonyLib; +using Microsoft.Xna.Framework; + +namespace Barotrauma.LuaCs; + +public class SettingsMenuSystem : ISettingsMenuSystem +{ + private GUIFrame _menuFrame; + private GUIButton _menuOpenButton; + private readonly Harmony _harmony; + private static SettingsMenuSystem _systemInstance; + + public SettingsMenuSystem() + { + _systemInstance = this; + _harmony = Harmony.CreateAndPatchAll(typeof(SettingsMenuSystem)); + } + + [HarmonyPatch(typeof(SettingsMenu), "CreateModsTab"), HarmonyPostfix] + private static void SettingsMenu_CreateModsTab_Post(SettingsMenu __instance) + { + _systemInstance.CreateSettingsMenu(__instance); + } + + private void CreateSettingsMenu(SettingsMenu __instance) + { + var tabIndex = (SettingsMenu.Tab)Enum.GetValues().Length; + var contentFrame = CreateNewContentFrame(tabIndex); + contentFrame.RectTransform.RelativeSize = Vector2.One; + + + + GUIFrame CreateNewContentFrame(SettingsMenu.Tab tab) + { + if (__instance.tabContents.TryGetValue(tab, out (GUIButton Button, GUIFrame Content) tabContent)) + { + return tabContent.Content; + } + + var contentFr = new GUIFrame(new RectTransform(Vector2.One * 0.95f, __instance.contentFrame.RectTransform, Anchor.Center, Pivot.Center), style: null); + + var button = new GUIButton(new RectTransform(Vector2.One, __instance.tabber.RectTransform, Anchor.TopLeft, Pivot.TopLeft, scaleBasis: ScaleBasis.Smallest), "", style: $"SettingsMenuTab.Mods") + { + ToolTip = TextManager.Get($"LuaCsForBarotrauma.SettingsMenu.ModSettingsButton"), + OnClicked = (b, _) => + { + __instance.SelectTab(tab); + return false; + } + }; + button.RectTransform.MaxSize = RectTransform.MaxPoint; + button.Children.ForEach(c => c.RectTransform.MaxSize = RectTransform.MaxPoint); + + __instance.tabContents.Add(tab, (button, contentFr)); + + return contentFr; + } + } + + private void DisposeMenuFrame() + { + if (_menuFrame is not null) + { + _menuFrame.Parent.RemoveChild(_menuFrame); + _menuFrame = null; + } + } + + #region DISPOSAL + + public void Dispose() + { + if (!ModUtils.Threading.CheckIfClearAndSetBool(ref _isDisposed)) + { + return; + } + DisposeMenuFrame(); + GC.SuppressFinalize(this); + } + private int _isDisposed = 0; + public bool IsDisposed + { + get => ModUtils.Threading.GetBool(ref _isDisposed); + private set => ModUtils.Threading.SetBool(ref _isDisposed, value); + } + public FluentResults.Result Reset() + { + throw new NotImplementedException(); + } + + #endregion +} diff --git a/Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/IClientLoggerService.cs b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/_Interfaces/IClientLoggerService.cs similarity index 100% rename from Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/IClientLoggerService.cs rename to Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/_Interfaces/IClientLoggerService.cs diff --git a/Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/IConfigService.cs b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/_Interfaces/IConfigService.cs similarity index 100% rename from Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/IConfigService.cs rename to Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/_Interfaces/IConfigService.cs diff --git a/Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/_Interfaces/ISettingsMenuService.cs b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/_Interfaces/ISettingsMenuService.cs new file mode 100644 index 000000000..906fa7971 --- /dev/null +++ b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/_Interfaces/ISettingsMenuService.cs @@ -0,0 +1,6 @@ +namespace Barotrauma.LuaCs; + +public interface ISettingsMenuSystem : ISystem +{ + +} diff --git a/Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/IUIStylesCollection.cs b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/_Interfaces/IUIStylesCollection.cs similarity index 100% rename from Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/IUIStylesCollection.cs rename to Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/_Interfaces/IUIStylesCollection.cs diff --git a/Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/IUIStylesService.cs b/Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/_Interfaces/IUIStylesService.cs similarity index 100% rename from Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/IUIStylesService.cs rename to Barotrauma/BarotraumaClient/ClientSource/LuaCs/Services/_Interfaces/IUIStylesService.cs diff --git a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen/MainMenuScreen.cs b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen/MainMenuScreen.cs index 233f6b666..45a7c141f 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen/MainMenuScreen.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Screens/MainMenuScreen/MainMenuScreen.cs @@ -531,7 +531,7 @@ namespace Barotrauma } }; #endif - new GUIButton(new RectTransform(new Point(300, 30), Frame.RectTransform, Anchor.TopLeft) { AbsoluteOffset = new Point(40, 50) }, + /*new GUIButton(new RectTransform(new Point(300, 30), Frame.RectTransform, Anchor.TopLeft) { AbsoluteOffset = new Point(40, 50) }, $"Open LuaCs Settings", style: "MainMenuGUIButton", color: GUIStyle.Red) { IgnoreLayoutGroups = true, @@ -540,7 +540,7 @@ namespace Barotrauma LuaCsSettingsMenu.Open(Frame.RectTransform); return true; } - }; + };*/ // TODO: Implement version reading. //string version = File.Exists(LuaCsSetup.VersionFile) ? File.ReadAllText(LuaCsSetup.VersionFile) : "Github"; diff --git a/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs b/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs index 34ebe4aca..7f9a9214a 100644 --- a/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs +++ b/Barotrauma/BarotraumaClient/ClientSource/Settings/SettingsMenu.cs @@ -33,10 +33,10 @@ namespace Barotrauma private GameSettings.Config unsavedConfig; - private readonly GUIFrame mainFrame; + public readonly GUIFrame mainFrame; - private readonly GUILayoutGroup tabber; - private readonly GUIFrame contentFrame; + public readonly GUILayoutGroup tabber; + public readonly GUIFrame contentFrame; private readonly GUILayoutGroup bottom; public readonly WorkshopMenu WorkshopMenu; @@ -103,7 +103,7 @@ namespace Barotrauma newContent.Visible = true; } - private readonly Dictionary tabContents; + public readonly Dictionary tabContents; public void SelectTab(Tab tab) { @@ -149,7 +149,7 @@ namespace Barotrauma return content; } - private static (GUILayoutGroup Left, GUILayoutGroup Right) CreateSidebars(GUIFrame parent, bool split = false) + public static (GUILayoutGroup Left, GUILayoutGroup Right) CreateSidebars(GUIFrame parent, bool split = false) { GUILayoutGroup layout = new GUILayoutGroup(new RectTransform(Vector2.One, parent.RectTransform), isHorizontal: true); GUILayoutGroup left = new GUILayoutGroup(new RectTransform((0.4875f, 1.0f), layout.RectTransform), isHorizontal: false); @@ -166,29 +166,29 @@ namespace Barotrauma return (left, right); } - private static GUILayoutGroup CreateCenterLayout(GUIFrame parent) + public static GUILayoutGroup CreateCenterLayout(GUIFrame parent) { return new GUILayoutGroup(new RectTransform((0.5f, 1.0f), parent.RectTransform, Anchor.TopCenter, Pivot.TopCenter)) { ChildAnchor = Anchor.TopCenter }; } - private static RectTransform NewItemRectT(GUILayoutGroup parent) + public static RectTransform NewItemRectT(GUILayoutGroup parent) => new RectTransform((1.0f, 0.06f), parent.RectTransform, Anchor.CenterLeft); - private static void Spacer(GUILayoutGroup parent) + public static void Spacer(GUILayoutGroup parent) { new GUIFrame(new RectTransform((1.0f, 0.03f), parent.RectTransform, Anchor.CenterLeft), style: null); } - private static GUITextBlock Label(GUILayoutGroup parent, LocalizedString str, GUIFont font) + public static GUITextBlock Label(GUILayoutGroup parent, LocalizedString str, GUIFont font) { return new GUITextBlock(NewItemRectT(parent), str, font: font); } - private static void DropdownEnum(GUILayoutGroup parent, Func textFunc, Func? tooltipFunc, T currentValue, + public static void DropdownEnum(GUILayoutGroup parent, Func textFunc, Func? tooltipFunc, T currentValue, Action setter) where T : Enum => Dropdown(parent, textFunc, tooltipFunc, (T[])Enum.GetValues(typeof(T)), currentValue, setter); - private static GUIDropDown Dropdown(GUILayoutGroup parent, Func textFunc, Func? tooltipFunc, IReadOnlyList values, T currentValue, Action setter) + public static GUIDropDown Dropdown(GUILayoutGroup parent, Func textFunc, Func? tooltipFunc, IReadOnlyList values, T currentValue, Action setter) { var dropdown = new GUIDropDown(NewItemRectT(parent), elementCount: values.Count); values.ForEach(v => dropdown.AddItem(text: textFunc(v), userData: v, toolTip: tooltipFunc?.Invoke(v) ?? null)); @@ -204,7 +204,7 @@ namespace Barotrauma return dropdown; } - private static (GUIScrollBar slider, GUITextBlock label) Slider(GUILayoutGroup parent, Vector2 range, int steps, Func labelFunc, float currentValue, Action setter, LocalizedString? tooltip = null) + public static (GUIScrollBar slider, GUITextBlock label) Slider(GUILayoutGroup parent, Vector2 range, int steps, Func labelFunc, float currentValue, Action setter, LocalizedString? tooltip = null) { var layout = new GUILayoutGroup(NewItemRectT(parent), isHorizontal: true); var slider = new GUIScrollBar(new RectTransform((0.72f, 1.0f), layout.RectTransform), style: "GUISlider") @@ -229,7 +229,7 @@ namespace Barotrauma return (slider, label); } - private static GUITickBox Tickbox(GUILayoutGroup parent, LocalizedString label, LocalizedString tooltip, bool currentValue, Action setter) + public static GUITickBox Tickbox(GUILayoutGroup parent, LocalizedString label, LocalizedString tooltip, bool currentValue, Action setter) { return new GUITickBox(NewItemRectT(parent), label) { @@ -243,9 +243,9 @@ namespace Barotrauma }; } - private string Percentage(float v) => ToolBox.GetFormattedPercentage(v); + public string Percentage(float v) => ToolBox.GetFormattedPercentage(v); - private static int Round(float v) => MathUtils.RoundToInt(v); + public static int Round(float v) => MathUtils.RoundToInt(v); private void CreateGraphicsTab() { @@ -965,4 +965,4 @@ namespace Barotrauma GUI.SettingsMenuOpen = false; } } -} \ No newline at end of file +} diff --git a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/filelist.xml b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/filelist.xml index 9b389d76a..445a2ad00 100644 --- a/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/filelist.xml +++ b/Barotrauma/BarotraumaShared/LocalMods/LuaCsForBarotrauma/filelist.xml @@ -1,5 +1,5 @@  - + diff --git a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/ServicesProvider.cs b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/ServicesProvider.cs index 9452de187..8bfad23f2 100644 --- a/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/ServicesProvider.cs +++ b/Barotrauma/BarotraumaShared/SharedSource/LuaCs/_Services/ServicesProvider.cs @@ -7,6 +7,7 @@ using System.Reflection; using System.Runtime.CompilerServices; using System.Threading; using LightInject; +using Microsoft.Toolkit.Diagnostics; namespace Barotrauma.LuaCs; @@ -15,14 +16,11 @@ public class ServicesProvider : IServicesProvider { private ServiceContainer _serviceContainerInst; private ServiceContainer ServiceContainer => _serviceContainerInst; - /// - /// Definition: [Key: InterfaceType, Value: ConcreteTypes] - /// - private readonly ConcurrentDictionary> _systemTypeDefs = new(); + /// /// Definition: [Key: ConcreteType, Value: TypeInstance] /// - private readonly ConcurrentDictionary _systemInstances = new(); + private ImmutableArray _systemInstances = ImmutableArray.Empty; private readonly ReaderWriterLockSlim _serviceLock = new(); public ServicesProvider() @@ -41,7 +39,6 @@ public class ServicesProvider : IServicesProvider if (typeof(TSvcInterface).IsAssignableTo(typeof(ISystem))) { lifetimeInstance = new PerContainerLifetime(); - _systemTypeDefs.GetOrAdd(typeof(TSvcInterface), (type) => new ConcurrentBag()); } if (lifetimeInstance is null) @@ -87,10 +84,9 @@ public class ServicesProvider : IServicesProvider } // ISystem services must run as a lifetime singleton - if (typeof(TSvcInterface).IsAssignableTo(typeof(ISystem))) + if (typeof(TService).IsAssignableTo(typeof(ISystem))) { lifetimeInstance = new PerContainerLifetime(); - _systemTypeDefs.GetOrAdd(typeof(TSvcInterface), (type) => new ConcurrentBag()); } if (lifetimeInstance is null) @@ -142,15 +138,15 @@ public class ServicesProvider : IServicesProvider try { _serviceLock.EnterWriteLock(); - ServiceContainer?.Compile(); - foreach (var typeDef in _systemTypeDefs.Values.SelectMany(type => type)) + ServiceContainer!.Compile(); + if (!_systemInstances.IsDefaultOrEmpty) { - if (_systemInstances.ContainsKey(typeDef)) - { - continue; - } - _systemInstances[typeDef] = (ISystem)ServiceContainer?.TryGetInstance(typeDef); + ThrowHelper.ThrowInvalidOperationException($"Systems are already instanced!"); } + + _systemInstances = ServiceContainer.GetAllInstances(typeof(ISystem)) + .Select(obj => (ISystem)obj) + .ToImmutableArray(); } finally { @@ -250,7 +246,7 @@ public class ServicesProvider : IServicesProvider try { _serviceLock.EnterWriteLock(); - foreach (var system in _systemInstances.Values) + foreach (var system in _systemInstances) { try { @@ -261,8 +257,7 @@ public class ServicesProvider : IServicesProvider // ignored, no logging services available. } } - _systemInstances.Clear(); - _systemTypeDefs.Clear(); + _systemInstances = ImmutableArray.Empty; _serviceContainerInst?.Dispose(); _serviceContainerInst = new ServiceContainer(); }