From 64bb8dbdd50e0b1e5744e1eb0cc6f24bda959ade Mon Sep 17 00:00:00 2001 From: c4llv07e <38111072+c4llv07e@users.noreply.github.com> Date: Mon, 1 Apr 2024 09:06:13 +0300 Subject: [PATCH] Add door electronics access configuration menu (#17778) * Add door electronics configuration menu * Use file-scoped namespaces Signed-off-by: c4llv07e * Open door electronics configuration menu only with network configurator Signed-off-by: c4llv07e * Doors will now try to move their AccessReaderComponent to their door electronics when the map is initialized Signed-off-by: c4llv07e * Make the access list in the id card computer a separate control Signed-off-by: c4llv07e * Fix merge conflict Signed-off-by: c4llv07e * Remove DoorElectronics tag Signed-off-by: c4llv07e * Integrate doors with #17927 Signed-off-by: c4llv07e * Move door electornics ui stuff to the right place Signed-off-by: c4llv07e * Some review fixes Signed-off-by: c4llv07e * More fixes Signed-off-by: c4llv07e * review fix Signed-off-by: c4llv07e * move all accesses from airlock prototypes to door electronics Signed-off-by: c4llv07e * rework door electronics config access list Signed-off-by: c4llv07e * Remove Linq from the door electronics user interface * [WIP] Add EntityWhitelist to the activatable ui component Signed-off-by: c4llv07e * Better interaction system Signed-off-by: c4llv07e * Refactor Signed-off-by: c4llv07e * Fix some door electronics not working without AccessReaderComponent Signed-off-by: c4llv07e * Move AccessReaderComponent update code to the AccessReaderSystem Signed-off-by: c4llv07e * Remove unnecesary newlines in the door access prototypes Signed-off-by: c4llv07e * Remove unused variables in access level control Signed-off-by: c4llv07e * Remove unnecessary method from the door electronics configuration menu Signed-off-by: c4llv07e * [WIP] change access type from string to ProtoId Signed-off-by: c4llv07e * Remove unused methods Signed-off-by: c4llv07e * Newline fix Signed-off-by: c4llv07e * Restored to a functional state Signed-off-by: c4llv07e * Fix access configurator not working with door electronics AccessReaderComponent Signed-off-by: c4llv07e * Replace all string access fields with ProtoId Signed-off-by: c4llv07e * move access level control initialization into Populate method Signed-off-by: c4llv07e * Review --------- Signed-off-by: c4llv07e Co-authored-by: metalgearsloth --- .../Access/UI/AccessLevelControl.xaml | 4 + .../Access/UI/AccessLevelControl.xaml.cs | 52 ++ .../UI/AccessOverriderBoundUserInterface.cs | 2 +- .../Access/UI/AccessOverriderWindow.xaml.cs | 17 +- .../UI/IdCardConsoleBoundUserInterface.cs | 4 +- .../Access/UI/IdCardConsoleWindow.xaml | 6 +- .../Access/UI/IdCardConsoleWindow.xaml.cs | 51 +- .../DoorElectronicsBoundUserInterface.cs | 59 ++ .../DoorElectronicsConfigurationMenu.xaml | 6 + .../DoorElectronicsConfigurationMenu.xaml.cs | 41 ++ .../Tests/Access/AccessReaderTest.cs | 60 +- .../Access/Systems/AccessOverriderSystem.cs | 42 +- .../Access/Systems/IdCardConsoleSystem.cs | 17 +- .../Systems/AdminVerbSystem.Tools.cs | 5 +- .../Systems/DoorElectronicsSystem.cs | 69 ++ Content.Server/Sandbox/SandboxSystem.cs | 3 +- .../EntitySystems/BluespaceLockerSystem.cs | 4 +- .../UserInterface/ActivatableUIComponent.cs | 13 +- .../UserInterface/ActivatableUISystem.cs | 11 +- Content.Shared/Access/AccessGroupPrototype.cs | 4 +- Content.Shared/Access/AccessLevelPrototype.cs | 8 + .../Access/Components/AccessComponent.cs | 12 +- .../Components/AccessOverriderComponent.cs | 16 +- .../Components/AccessReaderComponent.cs | 20 +- .../Components/IdCardConsoleComponent.cs | 20 +- .../Access/Systems/AccessReaderSystem.cs | 51 +- .../Access/Systems/SharedAccessSystem.cs | 6 +- .../Systems/SharedIdCardConsoleSystem.cs | 14 + .../Electronics/DoorElectronicsComponent.cs | 42 ++ Content.Shared/Random/RulesPrototype.cs | 4 +- Content.Shared/Roles/JobPrototype.cs | 16 +- .../Objects/Devices/Electronics/door.yml | 12 +- .../Devices/Electronics/door_access.yml | 264 +++++++ .../Structures/Doors/Airlocks/access.yml | 642 ++++++++---------- .../Doors/Airlocks/base_structureairlocks.yml | 3 +- .../Structures/Doors/Airlocks/highsec.yml | 1 + .../Graphs/structures/airlock.yml | 2 +- .../Graphs/structures/shutter.yml | 2 +- .../Graphs/structures/shuttle.yml | 2 +- .../Graphs/structures/windoor.yml | 4 +- 40 files changed, 1079 insertions(+), 532 deletions(-) create mode 100644 Content.Client/Access/UI/AccessLevelControl.xaml create mode 100644 Content.Client/Access/UI/AccessLevelControl.xaml.cs create mode 100644 Content.Client/Doors/Electronics/DoorElectronicsBoundUserInterface.cs create mode 100644 Content.Client/Doors/Electronics/DoorElectronicsConfigurationMenu.xaml create mode 100644 Content.Client/Doors/Electronics/DoorElectronicsConfigurationMenu.xaml.cs create mode 100644 Content.Server/Doors/Electronics/Systems/DoorElectronicsSystem.cs create mode 100644 Content.Shared/Doors/Electronics/DoorElectronicsComponent.cs create mode 100644 Resources/Prototypes/Entities/Objects/Devices/Electronics/door_access.yml diff --git a/Content.Client/Access/UI/AccessLevelControl.xaml b/Content.Client/Access/UI/AccessLevelControl.xaml new file mode 100644 index 0000000000..56968d8983 --- /dev/null +++ b/Content.Client/Access/UI/AccessLevelControl.xaml @@ -0,0 +1,4 @@ + + diff --git a/Content.Client/Access/UI/AccessLevelControl.xaml.cs b/Content.Client/Access/UI/AccessLevelControl.xaml.cs new file mode 100644 index 0000000000..34db80b7af --- /dev/null +++ b/Content.Client/Access/UI/AccessLevelControl.xaml.cs @@ -0,0 +1,52 @@ +using System.Linq; +using Robust.Client.AutoGenerated; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.XAML; +using Robust.Shared.Prototypes; +using Content.Shared.Access; +using Content.Shared.Access.Systems; + +namespace Content.Client.Access.UI; + +[GenerateTypedNameReferences] +public sealed partial class AccessLevelControl : GridContainer +{ + public readonly Dictionary, Button> ButtonsList = new(); + + public AccessLevelControl() + { + RobustXamlLoader.Load(this); + } + + public void Populate(List> accessLevels, IPrototypeManager prototypeManager) + { + foreach (var access in accessLevels) + { + if (!prototypeManager.TryIndex(access, out var accessLevel)) + { + Logger.Error($"Unable to find accesslevel for {access}"); + continue; + } + + var newButton = new Button + { + Text = accessLevel.GetAccessLevelName(), + ToggleMode = true, + }; + AddChild(newButton); + ButtonsList.Add(accessLevel.ID, newButton); + } + } + + public void UpdateState( + List> pressedList, + List>? enabledList = null) + { + foreach (var (accessName, button) in ButtonsList) + { + button.Pressed = pressedList.Contains(accessName); + button.Disabled = !(enabledList?.Contains(accessName) ?? true); + } + } +} diff --git a/Content.Client/Access/UI/AccessOverriderBoundUserInterface.cs b/Content.Client/Access/UI/AccessOverriderBoundUserInterface.cs index 0c23542f79..c1b63dc4d0 100644 --- a/Content.Client/Access/UI/AccessOverriderBoundUserInterface.cs +++ b/Content.Client/Access/UI/AccessOverriderBoundUserInterface.cs @@ -64,7 +64,7 @@ namespace Content.Client.Access.UI _window?.UpdateState(castState); } - public void SubmitData(List newAccessList) + public void SubmitData(List> newAccessList) { SendMessage(new WriteToTargetAccessReaderIdMessage(newAccessList)); } diff --git a/Content.Client/Access/UI/AccessOverriderWindow.xaml.cs b/Content.Client/Access/UI/AccessOverriderWindow.xaml.cs index 2fd0057121..6025c3b551 100644 --- a/Content.Client/Access/UI/AccessOverriderWindow.xaml.cs +++ b/Content.Client/Access/UI/AccessOverriderWindow.xaml.cs @@ -16,7 +16,6 @@ namespace Content.Client.Access.UI [Dependency] private readonly ILogManager _logManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - private readonly ISawmill _logMill = default!; private readonly AccessOverriderBoundUserInterface _owner; private readonly Dictionary _accessButtons = new(); @@ -25,7 +24,7 @@ namespace Content.Client.Access.UI { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); - _logMill = _logManager.GetSawmill(SharedAccessOverriderSystem.Sawmill); + var logMill = _logManager.GetSawmill(SharedAccessOverriderSystem.Sawmill); _owner = owner; @@ -33,13 +32,13 @@ namespace Content.Client.Access.UI { if (!prototypeManager.TryIndex(access, out var accessLevel)) { - _logMill.Error($"Unable to find accesslevel for {access}"); + logMill.Error($"Unable to find accesslevel for {access}"); continue; } var newButton = new Button { - Text = GetAccessLevelName(accessLevel), + Text = accessLevel.GetAccessLevelName(), ToggleMode = true, }; @@ -49,14 +48,6 @@ namespace Content.Client.Access.UI } } - private static string GetAccessLevelName(AccessLevelPrototype prototype) - { - if (prototype.Name is { } name) - return Loc.GetString(name); - - return prototype.ID; - } - public void UpdateState(AccessOverriderBoundUserInterfaceState state) { PrivilegedIdLabel.Text = state.PrivilegedIdName; @@ -105,7 +96,7 @@ namespace Content.Client.Access.UI _owner.SubmitData( // Iterate over the buttons dictionary, filter by `Pressed`, only get key from the key/value pair - _accessButtons.Where(x => x.Value.Pressed).Select(x => x.Key).ToList()); + _accessButtons.Where(x => x.Value.Pressed).Select(x => new ProtoId(x.Key)).ToList()); } } } diff --git a/Content.Client/Access/UI/IdCardConsoleBoundUserInterface.cs b/Content.Client/Access/UI/IdCardConsoleBoundUserInterface.cs index 898792aa03..5b7011c195 100644 --- a/Content.Client/Access/UI/IdCardConsoleBoundUserInterface.cs +++ b/Content.Client/Access/UI/IdCardConsoleBoundUserInterface.cs @@ -1,5 +1,6 @@ using Content.Shared.Access; using Content.Shared.Access.Components; +using Content.Shared.Access; using Content.Shared.Access.Systems; using Content.Shared.Containers.ItemSlots; using Content.Shared.CrewManifest; @@ -28,7 +29,6 @@ namespace Content.Client.Access.UI if (EntMan.TryGetComponent(Owner, out var idCard)) { accessLevels = idCard.AccessLevels; - accessLevels.Sort(); } else { @@ -65,7 +65,7 @@ namespace Content.Client.Access.UI _window?.UpdateState(castState); } - public void SubmitData(string newFullName, string newJobTitle, List newAccessList, string newJobPrototype) + public void SubmitData(string newFullName, string newJobTitle, List> newAccessList, string newJobPrototype) { if (newFullName.Length > MaxFullNameLength) newFullName = newFullName[..MaxFullNameLength]; diff --git a/Content.Client/Access/UI/IdCardConsoleWindow.xaml b/Content.Client/Access/UI/IdCardConsoleWindow.xaml index c29adc8ebd..a2f5f3382b 100644 --- a/Content.Client/Access/UI/IdCardConsoleWindow.xaml +++ b/Content.Client/Access/UI/IdCardConsoleWindow.xaml @@ -30,10 +30,6 @@