]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
uplink locking/unlocking, minor pda refactor (#15842)
authordeltanedas <39013340+deltanedas@users.noreply.github.com>
Mon, 1 May 2023 06:30:08 +0000 (06:30 +0000)
committerGitHub <noreply@github.com>
Mon, 1 May 2023 06:30:08 +0000 (16:30 +1000)
Co-authored-by: deltanedas <@deltanedas:kde.org>
13 files changed:
Content.Client/Store/Ui/StoreBoundUserInterface.cs
Content.Client/Store/Ui/StoreMenu.xaml
Content.Client/Store/Ui/StoreMenu.xaml.cs
Content.Server/Mind/Commands/RenameCommand.cs
Content.Server/PDA/PDASystem.cs
Content.Server/PDA/Ringer/RingerSystem.cs
Content.Server/PDA/Ringer/RingerUplinkComponent.cs
Content.Server/Station/Systems/StationSpawningSystem.cs
Content.Server/Store/Systems/StoreSystem.Ui.cs
Content.Server/Store/Systems/StoreSystem.cs
Content.Shared/Store/StoreUi.cs
Resources/Locale/en-US/game-ticking/game-presets/preset-traitor.ftl
Resources/Locale/en-US/store/store.ftl

index 2301d11248c21a25eb5e0509824547930760869a..8ff5ff1ca85af62bafddfa9bd250d41ae4bde0fa 100644 (file)
@@ -53,11 +53,14 @@ public sealed class StoreBoundUserInterface : BoundUserInterface
                 _menu.UpdateBalance(msg.Balance);
                 _menu.PopulateStoreCategoryButtons(msg.Listings);
                 _menu.UpdateListing(msg.Listings.ToList());
+                _menu.SetFooterVisibility(msg.ShowFooter);
                 break;
             case StoreInitializeState msg:
                 _windowName = msg.Name;
                 if (_menu != null && _menu.Window != null)
+                {
                     _menu.Window.Title = msg.Name;
+                }
                 break;
         }
     }
index fbbf6c13430e23be5eb955038742cc6f55e0e1c4..824c153671b7461ee3bcad9daaf6310e560a5bfb 100644 (file)
                 </BoxContainer>
             </PanelContainer>
         </BoxContainer>
+
+        <!-- Footer -->
+        <BoxContainer Orientation="Vertical" Name="TraitorFooter">
+            <PanelContainer StyleClasses="LowDivider" />
+            <BoxContainer Orientation="Horizontal" Margin="10 2 5 0" VerticalAlignment="Bottom">
+                <Label Text="{Loc 'store-ui-traitor-flavor'}" StyleClasses="WindowFooterText" />
+                <Label Text="{Loc 'store-ui-traitor-warning'}" StyleClasses="WindowFooterText"
+                        HorizontalAlignment="Right" HorizontalExpand="True"  Margin="0 0 5 0" />
+            </BoxContainer>
+        </BoxContainer>
     </BoxContainer>
 </DefaultWindow>
index f39101ed1664f27b11ccb6118151086499d6fef7..a3f246badba5c0b95249d7428710233a9cf1db71 100644 (file)
@@ -77,6 +77,11 @@ public sealed partial class StoreMenu : DefaultWindow
         }
     }
 
+    public void SetFooterVisibility(bool visible)
+    {
+        TraitorFooter.Visible = visible;
+    }
+
     private void OnWithdrawButtonDown(BaseButton.ButtonEventArgs args)
     {
         // check if window is already open
index 7efe3d9b4fbdc1cc9f80f2e28ac3313ced1a2658..0f92ae7c29634da670d6406cb63301baf6248fce 100644 (file)
@@ -82,11 +82,13 @@ public sealed class RenameCommand : IConsoleCommand
         // PDAs
         if (entSysMan.TryGetEntitySystem<PDASystem>(out var pdaSystem))
         {
-            foreach (var pdaComponent in entMan.EntityQuery<PDAComponent>())
+            var query = entMan.EntityQueryEnumerator<PDAComponent>();
+            while (query.MoveNext(out var uid, out var pda))
             {
-                if (pdaComponent.OwnerName != oldName)
-                    continue;
-                pdaSystem.SetOwner(pdaComponent, name);
+                if (pda.OwnerName == oldName)
+                {
+                    pdaSystem.SetOwner(uid, pda, name);
+                }
             }
         }
 
index 8362142c83663d688293540a55797d0279a39bfa..92bacf95b7f61ef33ee629782770422a142fe18a 100644 (file)
@@ -6,6 +6,8 @@ using Content.Server.Light.EntitySystems;
 using Content.Server.Light.Events;
 using Content.Server.PDA.Ringer;
 using Content.Server.Station.Systems;
+using Content.Server.Store.Components;
+using Content.Server.Store.Systems;
 using Content.Server.UserInterface;
 using Content.Shared.PDA;
 using Robust.Server.GameObjects;
@@ -18,12 +20,13 @@ namespace Content.Server.PDA
 {
     public sealed class PDASystem : SharedPDASystem
     {
+        [Dependency] private readonly CartridgeLoaderSystem _cartridgeLoader = default!;
+        [Dependency] private readonly InstrumentSystem _instrument = default!;
+        [Dependency] private readonly RingerSystem _ringer = default!;
+        [Dependency] private readonly StationSystem _station = default!;
+        [Dependency] private readonly StoreSystem _store = default!;
+        [Dependency] private readonly UserInterfaceSystem _ui = default!;
         [Dependency] private readonly UnpoweredFlashlightSystem _unpoweredFlashlight = default!;
-        [Dependency] private readonly RingerSystem _ringerSystem = default!;
-        [Dependency] private readonly InstrumentSystem _instrumentSystem = default!;
-        [Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
-        [Dependency] private readonly StationSystem _stationSystem = default!;
-        [Dependency] private readonly CartridgeLoaderSystem _cartridgeLoaderSystem = default!;
 
         public override void Initialize()
         {
@@ -40,43 +43,46 @@ namespace Content.Server.PDA
             if (!TryComp(uid, out ServerUserInterfaceComponent? uiComponent))
                 return;
 
-            UpdateStationName(pda);
+            UpdateStationName(uid, pda);
 
-            if (_uiSystem.TryGetUi(uid, PDAUiKey.Key, out var ui, uiComponent))
+            if (_ui.TryGetUi(uid, PDAUiKey.Key, out var ui, uiComponent))
                 ui.OnReceiveMessage += (msg) => OnUIMessage(pda, msg);
         }
 
         protected override void OnItemInserted(EntityUid uid, PDAComponent pda, EntInsertedIntoContainerMessage args)
         {
             base.OnItemInserted(uid, pda, args);
-            UpdatePDAUserInterface(pda);
+            UpdatePdaUi(uid, pda);
         }
 
         protected override void OnItemRemoved(EntityUid uid, PDAComponent pda, EntRemovedFromContainerMessage args)
         {
             base.OnItemRemoved(uid, pda, args);
-            UpdatePDAUserInterface(pda);
+            UpdatePdaUi(uid, pda);
         }
 
         private void OnLightToggle(EntityUid uid, PDAComponent pda, LightToggleEvent args)
         {
             pda.FlashlightOn = args.IsOn;
-            UpdatePDAUserInterface(pda);
+            UpdatePdaUi(uid, pda);
         }
 
-        public void SetOwner(PDAComponent pda, string ownerName)
+        public void SetOwner(EntityUid uid, PDAComponent pda, string ownerName)
         {
             pda.OwnerName = ownerName;
-            UpdatePDAUserInterface(pda);
+            UpdatePdaUi(uid, pda);
         }
 
         private void OnGridChanged(EntityUid uid, PDAComponent pda, GridModifiedEvent args)
         {
-            UpdateStationName(pda);
-            UpdatePDAUserInterface(pda);
+            UpdateStationName(uid, pda);
+            UpdatePdaUi(uid, pda);
         }
 
-        private void UpdatePDAUserInterface(PDAComponent pda)
+        /// <summary>
+        /// Send new UI state to clients, call if you modify something like uplink.
+        /// </summary>
+        public void UpdatePdaUi(EntityUid uid, PDAComponent pda)
         {
             var ownerInfo = new PDAIdInfoText
             {
@@ -85,49 +91,62 @@ namespace Content.Server.PDA
                 JobTitle = pda.ContainedID?.JobTitle
             };
 
-            if (!_uiSystem.TryGetUi(pda.Owner, PDAUiKey.Key, out var ui))
+            if (!_ui.TryGetUi(uid, PDAUiKey.Key, out var ui))
                 return;
 
-            var address = GetDeviceNetAddress(pda.Owner);
-            var hasInstrument = HasComp<InstrumentComponent>(pda.Owner);
-            var state = new PDAUpdateState(pda.FlashlightOn, pda.PenSlot.HasItem, ownerInfo, pda.StationName, false, hasInstrument, address);
+            var address = GetDeviceNetAddress(uid);
+            var hasInstrument = HasComp<InstrumentComponent>(uid);
+            var showUplink = HasComp<StoreComponent>(uid) && IsUnlocked(uid);
 
-            _cartridgeLoaderSystem?.UpdateUiState(pda.Owner, state);
+            var state = new PDAUpdateState(pda.FlashlightOn, pda.PenSlot.HasItem, ownerInfo, pda.StationName, showUplink, hasInstrument, address);
+            _cartridgeLoader?.UpdateUiState(uid, state);
         }
 
         private void OnUIMessage(PDAComponent pda, ServerBoundUserInterfaceMessage msg)
         {
-            var pdaEnt = pda.Owner;
+            var uid = pda.Owner;
             // todo: move this to entity events
             switch (msg.Message)
             {
                 case PDARequestUpdateInterfaceMessage _:
-                    UpdatePDAUserInterface(pda);
+                    UpdatePdaUi(uid, pda);
                     break;
                 case PDAToggleFlashlightMessage _:
                     {
-                        if (EntityManager.TryGetComponent(pdaEnt, out UnpoweredFlashlightComponent? flashlight))
-                            _unpoweredFlashlight.ToggleLight(pdaEnt, flashlight);
+                        if (TryComp<UnpoweredFlashlightComponent>(uid, out var flashlight))
+                            _unpoweredFlashlight.ToggleLight(uid, flashlight);
                         break;
                     }
                 case PDAShowRingtoneMessage _:
                     {
-                        if (EntityManager.TryGetComponent(pdaEnt, out RingerComponent? ringer))
-                            _ringerSystem.ToggleRingerUI(ringer, msg.Session);
+                        if (TryComp<RingerComponent>(uid, out var ringer))
+                            _ringer.ToggleRingerUI(ringer, msg.Session);
                         break;
                     }
                 case PDAShowMusicMessage _:
                 {
-                    if (TryComp(pdaEnt, out InstrumentComponent? instrument))
-                        _instrumentSystem.ToggleInstrumentUi(pdaEnt, msg.Session, instrument);
+                    if (TryComp<InstrumentComponent>(uid, out var instrument))
+                        _instrument.ToggleInstrumentUi(uid, msg.Session, instrument);
+                    break;
+                }
+                case PDAShowUplinkMessage _:
+                {
+                    // check if its locked again to prevent malicious clients opening locked uplinks
+                    if (TryComp<StoreComponent>(uid, out var store) && IsUnlocked(uid))
+                        _store.ToggleUi(msg.Session.AttachedEntity!.Value, uid, store);
                     break;
                 }
             }
         }
 
-        private void UpdateStationName(PDAComponent pda)
+        private bool IsUnlocked(EntityUid uid)
+        {
+            return TryComp<RingerUplinkComponent>(uid, out var uplink) ? uplink.Unlocked : true;
+        }
+
+        private void UpdateStationName(EntityUid uid, PDAComponent pda)
         {
-            var station = _stationSystem.GetOwningStation(pda.Owner);
+            var station = _station.GetOwningStation(uid);
             pda.StationName = station is null ? null : Name(station.Value);
         }
 
index b0b56bc740f6e35587fa049627d985d9f5ad98c5..a75dcce74d90b1f911443f1d4346c3db9f85f1e4 100644 (file)
@@ -3,6 +3,8 @@ using Content.Server.Store.Systems;
 using Content.Server.UserInterface;
 using Content.Shared.PDA;
 using Content.Shared.PDA.Ringer;
+using Content.Shared.Store;
+using Robust.Server.GameObjects;
 using Robust.Server.Player;
 using Robust.Shared.Audio;
 using Robust.Shared.Player;
@@ -14,8 +16,10 @@ namespace Content.Server.PDA.Ringer
 {
     public sealed class RingerSystem : SharedRingerSystem
     {
+        [Dependency] private readonly PDASystem _pda = default!;
         [Dependency] private readonly IRobustRandom _random = default!;
         [Dependency] private readonly StoreSystem _store = default!;
+        [Dependency] private readonly UserInterfaceSystem _ui = default!;
 
         public override void Initialize()
         {
@@ -26,7 +30,7 @@ namespace Content.Server.PDA.Ringer
             SubscribeLocalEvent<RingerUplinkComponent, ComponentInit>(RandomizeUplinkCode);
             // RingerBoundUserInterface Subscriptions
             SubscribeLocalEvent<RingerComponent, RingerSetRingtoneMessage>(OnSetRingtone);
-            SubscribeLocalEvent<RingerUplinkComponent, RingerSetRingtoneMessage>(OnSetUplinkRingtone);
+            SubscribeLocalEvent<RingerUplinkComponent, BeforeRingtoneSetEvent>(OnSetUplinkRingtone);
             SubscribeLocalEvent<RingerComponent, RingerPlayRingtoneMessage>(RingerPlayRingtone);
             SubscribeLocalEvent<RingerComponent, RingerRequestUpdateInterfaceMessage>(UpdateRingerUserInterfaceDriver);
 
@@ -50,17 +54,28 @@ namespace Content.Server.PDA.Ringer
             // Client sent us an updated ringtone so set it to that.
             if (args.Ringtone.Length != RingtoneLength) return;
 
+            var ev = new BeforeRingtoneSetEvent(args.Ringtone);
+            RaiseLocalEvent(uid, ref ev);
+            if (ev.Handled)
+                return;
+
             UpdateRingerRingtone(ringer, args.Ringtone);
         }
 
-        private void OnSetUplinkRingtone(EntityUid uid, RingerUplinkComponent uplink, RingerSetRingtoneMessage args)
+        private void OnSetUplinkRingtone(EntityUid uid, RingerUplinkComponent uplink, ref BeforeRingtoneSetEvent args)
         {
-            if (uplink.Code.SequenceEqual(args.Ringtone) &&
-                args.Session.AttachedEntity != null &&
-                TryComp<StoreComponent>(uid, out var store))
+            if (uplink.Code.SequenceEqual(args.Ringtone) && TryComp<StoreComponent>(uid, out var store))
             {
-                var user = args.Session.AttachedEntity.Value;
-                _store.ToggleUi(args.Session.AttachedEntity.Value, uid, store);
+                uplink.Unlocked = !uplink.Unlocked;
+                if (TryComp<PDAComponent>(uid, out var pda))
+                    _pda.UpdatePdaUi(uid, pda);
+
+                // can't keep store open after locking it
+                if (!uplink.Unlocked)
+                    _ui.TryCloseAll(uid, StoreUiKey.Key);
+
+                // no saving the code to prevent meta click set on sus guys pda -> wewlad
+                args.Handled = true;
             }
         }
 
@@ -161,3 +176,6 @@ namespace Content.Server.PDA.Ringer
         }
     }
 }
+
+[ByRefEvent]
+public record struct BeforeRingtoneSetEvent(Note[] Ringtone, bool Handled = false);
index 138c48fb221c041211d1fdf6757f2fc909389e88..a446468ee1b25a3b1d828c9cc5f55f449345a6f7 100644 (file)
@@ -10,9 +10,15 @@ namespace Content.Server.PDA.Ringer;
 public sealed class RingerUplinkComponent : Component
 {
     /// <summary>
-    /// Notes to set ringtone to in order to open the uplink.
+    /// Notes to set ringtone to in order to lock or unlock the uplink.
     /// Automatically initialized to random notes.
     /// </summary>
     [DataField("code")]
     public Note[] Code = new Note[RingerSystem.RingtoneLength];
+
+    /// <summary>
+    /// Whether to show the toggle uplink button in pda settings.
+    /// </summary>
+    [DataField("unlocked"), ViewVariables(VVAccess.ReadWrite)]
+    public bool Unlocked;
 }
index d8fece6575be777830cc3332a83987ba0331c885..fcd61ed066f163d53cc49a4aaa339262aee894ea 100644 (file)
@@ -231,7 +231,7 @@ public sealed class StationSpawningSystem : EntitySystem
 
         _accessSystem.SetAccessToJob(cardId, jobPrototype, extendedAccess);
 
-        _pdaSystem.SetOwner(pdaComponent, characterName);
+        _pdaSystem.SetOwner(idUid.Value, pdaComponent, characterName);
     }
 
 
index 2ad246c290be4a3fb6989ecaa6c59f419fb664bc..cde624ef72e9ccc38811c02c88fdb8e10eaa6372 100644 (file)
@@ -1,5 +1,6 @@
 using Content.Server.Actions;
 using Content.Server.Administration.Logs;
+using Content.Server.PDA.Ringer;
 using Content.Server.Stack;
 using Content.Server.Store.Components;
 using Content.Server.UserInterface;
@@ -49,6 +50,17 @@ public sealed partial class StoreSystem
         UpdateUserInterface(user, storeEnt, component);
     }
 
+    /// <summary>
+    /// Closes the store UI for everyone, if it's open
+    /// </summary>
+    public void CloseUi(EntityUid uid, StoreComponent? component = null)
+    {
+        if (!Resolve(uid, ref component))
+            return;
+
+        _ui.TryCloseAll(uid, StoreUiKey.Key);
+    }
+
     /// <summary>
     /// Updates the user interface for a store and refreshes the listings
     /// </summary>
@@ -83,7 +95,9 @@ public sealed partial class StoreSystem
         // TODO: if multiple users are supposed to be able to interact with a single BUI & see different
         // stores/listings, this needs to use session specific BUI states.
 
-        var state = new StoreUpdateState(component.LastAvailableListings, allCurrency);
+        // only tell operatives to lock their uplink if it can be locked
+        var showFooter = HasComp<RingerUplinkComponent>(store);
+        var state = new StoreUpdateState(component.LastAvailableListings, allCurrency, showFooter);
         _ui.SetUiState(ui, state);
     }
 
index d596f6ac4c5198929ff2a613730eea2ef68cc76f..e4a4410e22fe83b05ab4910d8158664c20296252 100644 (file)
@@ -1,4 +1,5 @@
 using Content.Server.Mind.Components;
+using Content.Server.PDA.Ringer;
 using Content.Server.Store.Components;
 using Content.Server.UserInterface;
 using Content.Shared.FixedPoint;
@@ -72,9 +73,9 @@ public sealed partial class StoreSystem : EntitySystem
         if (args.Target == null || !TryComp<StoreComponent>(args.Target, out var store))
             return;
 
-        // require the store to be open before inserting currency
+        // if the store can be locked, it must be unlocked first before inserting currency
         var user = args.User;
-        if (!TryComp<ActorComponent>(user, out var actor) || !_ui.SessionHasOpenUi(uid, StoreUiKey.Key, actor.PlayerSession))
+        if (TryComp<RingerUplinkComponent>(args.Target, out var uplink) && !uplink.Unlocked)
             return;
 
         args.Handled = TryAddCurrency(GetCurrencyValue(uid, component), args.Target.Value, store);
@@ -183,6 +184,8 @@ public sealed partial class StoreSystem : EntitySystem
 
         var ui = _ui.GetUiOrNull(uid, StoreUiKey.Key);
         if (ui != null)
+        {
             _ui.SetUiState(ui, new StoreInitializeState(preset.StoreName));
+        }
     }
 }
index 6e3838d36849f84ad6724a954da65b91db3d1aac..a142cf4e4fba887ec4541c594f49d68541453f17 100644 (file)
@@ -16,10 +16,13 @@ public sealed class StoreUpdateState : BoundUserInterfaceState
 
     public readonly Dictionary<string, FixedPoint2> Balance;
 
-    public StoreUpdateState(HashSet<ListingData> listings, Dictionary<string, FixedPoint2> balance)
+    public readonly bool ShowFooter;
+
+    public StoreUpdateState(HashSet<ListingData> listings, Dictionary<string, FixedPoint2> balance, bool showFooter)
     {
         Listings = listings;
         Balance = balance;
+        ShowFooter = showFooter;
     }
 }
 
index 872636165bb21122be2747469b0e14440726cc1e..5ce0d5be1fcc8c598712f47eef387eb757aa3760 100644 (file)
@@ -53,7 +53,7 @@ traitor-role-codewords =
     Listen for them, and keep them secret.
 traitor-role-uplink-code =
     Set your ringtone to the notes {$code} to lock or unlock your uplink.
-    Remember to lock it and change it, or the stations crew will easily open it too!
+    Remember to lock it after, or the stations crew will easily open it too!
 
 # don't need all the flavour text for character menu
 traitor-role-codewords-short =
index 96778ef47f477adf83d89fe6a8015b5ac9b063b7..7af2b0553380c74cdacdf1518f8315c10fb35ece 100644 (file)
@@ -2,5 +2,7 @@ store-ui-default-title = Store
 store-ui-default-withdraw-text = Withdraw
 store-ui-balance-display = {$currency}: {$amount}
 store-ui-price-display = {$amount} {$currency}
+store-ui-traitor-flavor = Copyright (C) NT -30643
+store-ui-traitor-warning = Operatives must lock their uplinks after use to avoid detection.
 
-store-withdraw-button-ui = Withdraw {$currency}
\ No newline at end of file
+store-withdraw-button-ui = Withdraw {$currency}