From e627a0d24bc8ae89665feb0b0d519b5fbb77ce32 Mon Sep 17 00:00:00 2001 From: Plykiya <58439124+Plykiya@users.noreply.github.com> Date: Thu, 21 Mar 2024 17:19:52 -0700 Subject: [PATCH] Door Remote now shows Mode in UI (#26162) * Prep for DoorRemote Status * Door Remote Mode Messages * plural opens and closes * never trust webedits --------- Co-authored-by: Plykiya --- .../Remotes/EntitySystems/DoorRemoteSystem.cs | 16 +++++ .../Remotes/UI/DoorRemoteStatusControl.cs | 46 +++++++++++++ Content.Server/Remotes/DoorRemoteComponent.cs | 16 ----- Content.Server/Remotes/DoorRemoteSystem.cs | 65 ++++--------------- .../Remotes/Components/DoorRemoteComponent.cs | 19 ++++++ .../EntitySystems/SharedDoorRemoteSystem.cs | 47 ++++++++++++++ .../Locale/en-US/door-remote/door-remote.ftl | 9 +++ 7 files changed, 151 insertions(+), 67 deletions(-) create mode 100644 Content.Client/Remotes/EntitySystems/DoorRemoteSystem.cs create mode 100644 Content.Client/Remotes/UI/DoorRemoteStatusControl.cs delete mode 100644 Content.Server/Remotes/DoorRemoteComponent.cs create mode 100644 Content.Shared/Remotes/Components/DoorRemoteComponent.cs create mode 100644 Content.Shared/Remotes/EntitySystems/SharedDoorRemoteSystem.cs diff --git a/Content.Client/Remotes/EntitySystems/DoorRemoteSystem.cs b/Content.Client/Remotes/EntitySystems/DoorRemoteSystem.cs new file mode 100644 index 0000000000..d6a9057f08 --- /dev/null +++ b/Content.Client/Remotes/EntitySystems/DoorRemoteSystem.cs @@ -0,0 +1,16 @@ +using Content.Client.Remote.UI; +using Content.Client.Items; +using Content.Shared.Remotes.EntitySystems; +using Content.Shared.Remotes.Components; + +namespace Content.Client.Remotes.EntitySystems; + +public sealed class DoorRemoteSystem : SharedDoorRemoteSystem +{ + public override void Initialize() + { + base.Initialize(); + + Subs.ItemStatus(ent => new DoorRemoteStatusControl(ent)); + } +} diff --git a/Content.Client/Remotes/UI/DoorRemoteStatusControl.cs b/Content.Client/Remotes/UI/DoorRemoteStatusControl.cs new file mode 100644 index 0000000000..94589ecdaa --- /dev/null +++ b/Content.Client/Remotes/UI/DoorRemoteStatusControl.cs @@ -0,0 +1,46 @@ +using Content.Client.Message; +using Content.Client.Stylesheets; +using Content.Shared.Remotes.Components; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Shared.Timing; + +namespace Content.Client.Remote.UI; + +public sealed class DoorRemoteStatusControl : Control +{ + private readonly Entity _entity; + private readonly RichTextLabel _label; + + // set to toggle bolts initially just so that it updates on first pickup of remote + private OperatingMode PrevOperatingMode = OperatingMode.placeholderForUiUpdates; + + public DoorRemoteStatusControl(Entity entity) + { + _entity = entity; + _label = new RichTextLabel { StyleClasses = { StyleNano.StyleClassItemStatus } }; + AddChild(_label); + } + + protected override void FrameUpdate(FrameEventArgs args) + { + base.FrameUpdate(args); + + // only updates the UI if any of the details are different than they previously were + if (PrevOperatingMode == _entity.Comp.Mode) + return; + + PrevOperatingMode = _entity.Comp.Mode; + + // Update current volume and injector state + var modeStringLocalized = Loc.GetString(_entity.Comp.Mode switch + { + OperatingMode.OpenClose => "door-remote-open-close-text", + OperatingMode.ToggleBolts => "door-remote-toggle-bolt-text", + OperatingMode.ToggleEmergencyAccess => "door-remote-emergency-access-text", + _ => "door-remote-invalid-text" + }); + + _label.SetMarkup(Loc.GetString("door-remote-mode-label", ("modeString", modeStringLocalized))); + } +} diff --git a/Content.Server/Remotes/DoorRemoteComponent.cs b/Content.Server/Remotes/DoorRemoteComponent.cs deleted file mode 100644 index 91cb7ccad1..0000000000 --- a/Content.Server/Remotes/DoorRemoteComponent.cs +++ /dev/null @@ -1,16 +0,0 @@ -namespace Content.Server.Remotes -{ - [RegisterComponent] - [Access(typeof(DoorRemoteSystem))] - public sealed partial class DoorRemoteComponent : Component - { - public OperatingMode Mode = OperatingMode.OpenClose; - - public enum OperatingMode : byte - { - OpenClose, - ToggleBolts, - ToggleEmergencyAccess - } - } -} diff --git a/Content.Server/Remotes/DoorRemoteSystem.cs b/Content.Server/Remotes/DoorRemoteSystem.cs index cb3243cb83..57ca0988d9 100644 --- a/Content.Server/Remotes/DoorRemoteSystem.cs +++ b/Content.Server/Remotes/DoorRemoteSystem.cs @@ -1,74 +1,40 @@ using Content.Server.Administration.Logs; -using Robust.Shared.Player; using Content.Shared.Interaction; -using Content.Shared.Popups; using Content.Shared.Doors.Components; -using Content.Shared.Doors.Systems; -using Content.Shared.Physics; using Content.Shared.Access.Components; using Content.Server.Doors.Systems; using Content.Server.Power.EntitySystems; using Content.Shared.Database; -using Content.Shared.Interaction.Events; using Content.Shared.Examine; -using static Content.Server.Remotes.DoorRemoteComponent; +using Content.Shared.Remotes.EntitySystems; +using Content.Shared.Remotes.Components; -namespace Content.Server.Remotes +namespace Content.Shared.Remotes { - public sealed class DoorRemoteSystem : EntitySystem + public sealed class DoorRemoteSystem : SharedDoorRemoteSystem { [Dependency] private readonly IAdminLogManager _adminLogger = default!; [Dependency] private readonly AirlockSystem _airlock = default!; - [Dependency] private readonly SharedPopupSystem _popupSystem = default!; [Dependency] private readonly DoorSystem _doorSystem = default!; - [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; [Dependency] private readonly ExamineSystemShared _examine = default!; - // I'm so sorry [Dependency] private readonly SharedAirlockSystem _sharedAirlockSystem = default!; - public override void Initialize() { - SubscribeLocalEvent(OnInHandActivation); + base.Initialize(); + SubscribeLocalEvent(OnBeforeInteract); } - public void OnInHandActivation(EntityUid user, DoorRemoteComponent component, UseInHandEvent args) - { - string switchMessageId; - switch (component.Mode) - { - case OperatingMode.OpenClose: - component.Mode = OperatingMode.ToggleBolts; - switchMessageId = "door-remote-switch-state-toggle-bolts"; - break; - - // Skip toggle bolts mode and move on from there (to emergency access) - case OperatingMode.ToggleBolts: - component.Mode = OperatingMode.ToggleEmergencyAccess; - switchMessageId = "door-remote-switch-state-toggle-emergency-access"; - break; - - // Skip ToggleEmergencyAccess mode and move on from there (to door toggle) - case OperatingMode.ToggleEmergencyAccess: - component.Mode = OperatingMode.OpenClose; - switchMessageId = "door-remote-switch-state-open-close"; - break; - default: - throw new InvalidOperationException( - $"{nameof(DoorRemoteComponent)} had invalid mode {component.Mode}"); - } - ShowPopupToUser(switchMessageId, args.User); - } - - private void OnBeforeInteract(EntityUid uid, DoorRemoteComponent component, BeforeRangedInteractEvent args) + private void OnBeforeInteract(Entity entity, ref BeforeRangedInteractEvent args) { bool isAirlock = TryComp(args.Target, out var airlockComp); if (args.Handled || args.Target == null || !TryComp(args.Target, out var doorComp) // If it isn't a door we don't use it - // Only able to control doors if they are within your vision and within your max range. - // Not affected by mobs or machines anymore. + // Only able to control doors if they are within your vision and within your max range. + // Not affected by mobs or machines anymore. || !_examine.InRangeUnOccluded(args.User, args.Target.Value, SharedInteractionSystem.MaxRaycastRange, null)) + { return; } @@ -77,7 +43,7 @@ namespace Content.Server.Remotes if (!this.IsPowered(args.Target.Value, EntityManager)) { - ShowPopupToUser("door-remote-no-power", args.User); + Popup.PopupEntity(Loc.GetString("door-remote-no-power"), args.User, args.User); return; } @@ -87,11 +53,11 @@ namespace Content.Server.Remotes && !_doorSystem.HasAccess(args.Target.Value, args.User, doorComp, accessComponent)) { _doorSystem.Deny(args.Target.Value, doorComp, args.User); - ShowPopupToUser("door-remote-denied", args.User); + Popup.PopupEntity(Loc.GetString("door-remote-denied"), args.User, args.User); return; } - switch (component.Mode) + switch (entity.Comp.Mode) { case OperatingMode.OpenClose: // Note we provide args.User here to TryToggleDoor as the "user" @@ -120,11 +86,8 @@ namespace Content.Server.Remotes break; default: throw new InvalidOperationException( - $"{nameof(DoorRemoteComponent)} had invalid mode {component.Mode}"); + $"{nameof(DoorRemoteComponent)} had invalid mode {entity.Comp.Mode}"); } } - - private void ShowPopupToUser(string messageId, EntityUid user) => - _popupSystem.PopupEntity(Loc.GetString(messageId), user, user); } } diff --git a/Content.Shared/Remotes/Components/DoorRemoteComponent.cs b/Content.Shared/Remotes/Components/DoorRemoteComponent.cs new file mode 100644 index 0000000000..b157596e3b --- /dev/null +++ b/Content.Shared/Remotes/Components/DoorRemoteComponent.cs @@ -0,0 +1,19 @@ +using Robust.Shared.GameStates; + +namespace Content.Shared.Remotes.Components; + +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +public sealed partial class DoorRemoteComponent : Component +{ + [AutoNetworkedField] + [DataField] + public OperatingMode Mode = OperatingMode.OpenClose; +} + +public enum OperatingMode : byte +{ + OpenClose, + ToggleBolts, + ToggleEmergencyAccess, + placeholderForUiUpdates +} diff --git a/Content.Shared/Remotes/EntitySystems/SharedDoorRemoteSystem.cs b/Content.Shared/Remotes/EntitySystems/SharedDoorRemoteSystem.cs new file mode 100644 index 0000000000..72d807e6a0 --- /dev/null +++ b/Content.Shared/Remotes/EntitySystems/SharedDoorRemoteSystem.cs @@ -0,0 +1,47 @@ +using Content.Shared.Interaction; +using Content.Shared.Popups; +using Content.Shared.Interaction.Events; +using Content.Shared.Remotes.Components; + +namespace Content.Shared.Remotes.EntitySystems; + +public abstract class SharedDoorRemoteSystem : EntitySystem +{ + [Dependency] protected readonly SharedPopupSystem Popup = default!; + [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; + // I'm so sorry [Dependency] private readonly SharedAirlockSystem _sharedAirlockSystem = default!; + + public override void Initialize() + { + SubscribeLocalEvent(OnInHandActivation); + } + + private void OnInHandActivation(Entity entity, ref UseInHandEvent args) + { + string switchMessageId; + switch (entity.Comp.Mode) + { + case OperatingMode.OpenClose: + entity.Comp.Mode = OperatingMode.ToggleBolts; + switchMessageId = "door-remote-switch-state-toggle-bolts"; + break; + + // Skip toggle bolts mode and move on from there (to emergency access) + case OperatingMode.ToggleBolts: + entity.Comp.Mode = OperatingMode.ToggleEmergencyAccess; + switchMessageId = "door-remote-switch-state-toggle-emergency-access"; + break; + + // Skip ToggleEmergencyAccess mode and move on from there (to door toggle) + case OperatingMode.ToggleEmergencyAccess: + entity.Comp.Mode = OperatingMode.OpenClose; + switchMessageId = "door-remote-switch-state-open-close"; + break; + default: + throw new InvalidOperationException( + $"{nameof(DoorRemoteComponent)} had invalid mode {entity.Comp.Mode}"); + } + Dirty(entity); + Popup.PopupClient(Loc.GetString(switchMessageId), entity, args.User); + } +} diff --git a/Resources/Locale/en-US/door-remote/door-remote.ftl b/Resources/Locale/en-US/door-remote/door-remote.ftl index bf2fc11861..2c4ccd0805 100644 --- a/Resources/Locale/en-US/door-remote/door-remote.ftl +++ b/Resources/Locale/en-US/door-remote/door-remote.ftl @@ -1,3 +1,12 @@ +## UI +door-remote-open-close-text = Opens and Closes Doors +door-remote-toggle-bolt-text = Toggles Bolts +door-remote-emergency-access-text = Toggles Emergency Access +door-remote-invalid-text = Invalid +door-remote-mode-label = Mode: [color=white]{$modeString}[/color] + +## Entity + door-remote-switch-state-open-close = You switch the remote to open and close doors door-remote-switch-state-toggle-bolts = You switch the remote to toggle bolts door-remote-switch-state-toggle-emergency-access = You switch the remote to toggle emergency access