From d03ca61da100b4c52c98f59ac448ecf58f4a733b Mon Sep 17 00:00:00 2001 From: Slava0135 <40753025+Slava0135@users.noreply.github.com> Date: Fri, 24 Mar 2023 03:09:45 +0300 Subject: [PATCH] Telecom server panel check (#14523) --- Content.Client/Wires/WiresSystem.cs | 7 ++ .../Tests/VendingMachineRestockTest.cs | 10 ++- .../Atmos/Monitor/Systems/AirAlarmSystem.cs | 11 +-- .../Construction/Conditions/WirePanel.cs | 13 ++- .../Construction/PartExchangerSystem.cs | 4 +- Content.Server/Doors/Systems/AirlockSystem.cs | 11 ++- Content.Server/Mech/Systems/MechSystem.cs | 4 +- .../ActivatableUIRequiresPowerSystem.cs | 51 ++++++------ .../Restock/VendingMachineRestockSystem.cs | 4 +- Content.Server/Wires/WiresComponent.cs | 25 ------ Content.Server/Wires/WiresSystem.cs | 83 ++++++++++--------- .../EntitySystems/EncryptionKeySystem.cs | 56 ++++++++----- Content.Shared/Wires/SharedWiresSystem.cs | 39 +++++++++ Content.Shared/Wires/WiresPanelComponent.cs | 41 +++++++++ .../components/encryption-key-component.ftl | 1 + .../wires/components/wires-component.ftl | 2 - .../components/wires-panel-component.ftl | 2 + 17 files changed, 226 insertions(+), 138 deletions(-) create mode 100644 Content.Client/Wires/WiresSystem.cs create mode 100644 Content.Shared/Wires/SharedWiresSystem.cs create mode 100644 Content.Shared/Wires/WiresPanelComponent.cs create mode 100644 Resources/Locale/en-US/wires/components/wires-panel-component.ftl diff --git a/Content.Client/Wires/WiresSystem.cs b/Content.Client/Wires/WiresSystem.cs new file mode 100644 index 0000000000..c2ffa978d1 --- /dev/null +++ b/Content.Client/Wires/WiresSystem.cs @@ -0,0 +1,7 @@ +using Content.Shared.Wires; + +namespace Content.Client.Wires; + +public sealed class WiresSystem : SharedWiresSystem +{ +} diff --git a/Content.IntegrationTests/Tests/VendingMachineRestockTest.cs b/Content.IntegrationTests/Tests/VendingMachineRestockTest.cs index 49207b5f55..6ff6b23dc7 100644 --- a/Content.IntegrationTests/Tests/VendingMachineRestockTest.cs +++ b/Content.IntegrationTests/Tests/VendingMachineRestockTest.cs @@ -9,11 +9,12 @@ using Robust.Shared.Prototypes; using Content.Server.Storage.Components; using Content.Server.VendingMachines; using Content.Server.VendingMachines.Restock; -using Content.Server.Wires; using Content.Shared.Cargo.Prototypes; using Content.Shared.Damage; using Content.Shared.Damage.Prototypes; using Content.Shared.VendingMachines; +using Content.Shared.Wires; +using Content.Server.Wires; namespace Content.IntegrationTests.Tests { @@ -188,7 +189,7 @@ namespace Content.IntegrationTests.Tests VendingMachineComponent machineComponent; VendingMachineRestockComponent restockRightComponent; VendingMachineRestockComponent restockWrongComponent; - WiresComponent machineWires; + WiresPanelComponent machineWiresPanel; var testMap = await PoolManager.CreateTestMap(pairTracker); @@ -206,7 +207,7 @@ namespace Content.IntegrationTests.Tests Assert.True(entityManager.TryGetComponent(machine, out machineComponent!), $"Machine has no {nameof(VendingMachineComponent)}"); Assert.True(entityManager.TryGetComponent(packageRight, out restockRightComponent!), $"Correct package has no {nameof(VendingMachineRestockComponent)}"); Assert.True(entityManager.TryGetComponent(packageWrong, out restockWrongComponent!), $"Wrong package has no {nameof(VendingMachineRestockComponent)}"); - Assert.True(entityManager.TryGetComponent(machine, out machineWires!), $"Machine has no {nameof(WiresComponent)}"); + Assert.True(entityManager.TryGetComponent(machine, out machineWiresPanel!), $"Machine has no {nameof(WiresPanelComponent)}"); var systemRestock = entitySystemManager.GetEntitySystem(); var systemMachine = entitySystemManager.GetEntitySystem(); @@ -215,8 +216,9 @@ namespace Content.IntegrationTests.Tests Assert.That(systemRestock.TryAccessMachine(packageRight, restockRightComponent, machineComponent, user, machine), Is.False, "Right package is able to restock without opened access panel"); Assert.That(systemRestock.TryAccessMachine(packageWrong, restockWrongComponent, machineComponent, user, machine), Is.False, "Wrong package is able to restock without opened access panel"); + var systemWires = entitySystemManager.GetEntitySystem(); // Open the panel. - machineWires.IsPanelOpen = true; + systemWires.TogglePanel(machine, machineWiresPanel, true); // Test that the right package works for the right machine. Assert.That(systemRestock.TryAccessMachine(packageRight, restockRightComponent, machineComponent, user, machine), Is.True, "Correct package is unable to restock with access panel opened"); diff --git a/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs b/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs index 94ff71ba77..8f6cf55dec 100644 --- a/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs +++ b/Content.Server/Atmos/Monitor/Systems/AirAlarmSystem.cs @@ -7,7 +7,6 @@ using Content.Server.DeviceNetwork.Systems; using Content.Server.Popups; using Content.Server.Power.Components; using Content.Server.Power.EntitySystems; -using Content.Server.Wires; using Content.Shared.Access.Components; using Content.Shared.Access.Systems; using Content.Shared.Atmos; @@ -16,8 +15,8 @@ using Content.Shared.Atmos.Monitor.Components; using Content.Shared.Atmos.Piping.Unary.Components; using Content.Shared.DeviceNetwork; using Content.Shared.Interaction; +using Content.Shared.Wires; using Robust.Server.GameObjects; -using Robust.Shared.Player; namespace Content.Server.Atmos.Monitor.Systems; @@ -227,10 +226,10 @@ public sealed class AirAlarmSystem : EntitySystem if (!_interactionSystem.InRangeUnobstructed(args.User, args.Target)) return; - if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor)) + if (!TryComp(args.User, out var actor)) return; - if (EntityManager.TryGetComponent(uid, out WiresComponent? wire) && wire.IsPanelOpen) + if (TryComp(uid, out var panel) && panel.Open) { args.Handled = false; return; @@ -239,7 +238,9 @@ public sealed class AirAlarmSystem : EntitySystem if (!this.IsPowered(uid, EntityManager)) return; - _uiSystem.GetUiOrNull(component.Owner, SharedAirAlarmInterfaceKey.Key)?.Open(actor.PlayerSession); + var ui = _uiSystem.GetUiOrNull(uid, SharedAirAlarmInterfaceKey.Key); + if (ui != null) + _uiSystem.OpenUi(ui, actor.PlayerSession); component.ActivePlayers.Add(actor.PlayerSession.UserId); AddActiveInterface(uid); SyncAllDevices(uid); diff --git a/Content.Server/Construction/Conditions/WirePanel.cs b/Content.Server/Construction/Conditions/WirePanel.cs index 224ad32938..a4c478026e 100644 --- a/Content.Server/Construction/Conditions/WirePanel.cs +++ b/Content.Server/Construction/Conditions/WirePanel.cs @@ -1,6 +1,6 @@ -using Content.Server.Wires; using Content.Shared.Construction; using Content.Shared.Examine; +using Content.Shared.Wires; using JetBrains.Annotations; namespace Content.Server.Construction.Conditions @@ -14,24 +14,23 @@ namespace Content.Server.Construction.Conditions public bool Condition(EntityUid uid, IEntityManager entityManager) { //if it doesn't have a wire panel, then just let it work. - if (!entityManager.TryGetComponent(uid, out WiresComponent? wires)) + if (!entityManager.TryGetComponent(uid, out var wires)) return true; - return wires.IsPanelOpen == Open; + return wires.Open == Open; } public bool DoExamine(ExaminedEvent args) { var entity = args.Examined; - - if (!IoCManager.Resolve().TryGetComponent(entity, out WiresComponent? wires)) return false; + if (!IoCManager.Resolve().TryGetComponent(entity, out var panel)) return false; switch (Open) { - case true when !wires.IsPanelOpen: + case true when !panel.Open: args.PushMarkup(Loc.GetString("construction-examine-condition-wire-panel-open")); return true; - case false when wires.IsPanelOpen: + case false when panel.Open: args.PushMarkup(Loc.GetString("construction-examine-condition-wire-panel-close")); return true; } diff --git a/Content.Server/Construction/PartExchangerSystem.cs b/Content.Server/Construction/PartExchangerSystem.cs index 837bf808db..c865f47926 100644 --- a/Content.Server/Construction/PartExchangerSystem.cs +++ b/Content.Server/Construction/PartExchangerSystem.cs @@ -3,13 +3,13 @@ using Content.Server.Construction.Components; using Content.Server.DoAfter; using Content.Server.Storage.Components; using Content.Server.Storage.EntitySystems; -using Content.Server.Wires; using Content.Shared.DoAfter; using Content.Shared.Construction.Components; using Content.Shared.Interaction; using Content.Shared.Popups; using Robust.Shared.Containers; using Robust.Shared.Utility; +using Content.Shared.Wires; namespace Content.Server.Construction; @@ -103,7 +103,7 @@ public sealed class PartExchangerSystem : EntitySystem if (!HasComp(args.Target)) return; - if (TryComp(args.Target, out var wires) && !wires.IsPanelOpen) + if (TryComp(args.Target, out var panel) && !panel.Open) { _popup.PopupEntity(Loc.GetString("construction-step-condition-wire-panel-open"), args.Target.Value); diff --git a/Content.Server/Doors/Systems/AirlockSystem.cs b/Content.Server/Doors/Systems/AirlockSystem.cs index e39f5bd9c2..e5e73204fc 100644 --- a/Content.Server/Doors/Systems/AirlockSystem.cs +++ b/Content.Server/Doors/Systems/AirlockSystem.cs @@ -7,6 +7,7 @@ using Content.Shared.Doors.Components; using Content.Shared.Doors.Systems; using Content.Shared.Interaction; using Robust.Server.GameObjects; +using Content.Shared.Wires; namespace Content.Server.Doors.Systems { @@ -71,11 +72,9 @@ namespace Content.Server.Doors.Systems // means that sometimes the panels & bolt lights may be visible despite a door being completely open. // Only show the maintenance panel if the airlock is closed - if (TryComp(uid, out var wiresComponent)) + if (TryComp(uid, out var wiresPanel)) { - wiresComponent.IsPanelVisible = - component.OpenPanelVisible - || args.State != DoorState.Open; + _wiresSystem.ChangePanelVisibility(uid, wiresPanel, component.OpenPanelVisible || args.State != DoorState.Open); } // If the door is closed, we should look if the bolt was locked while closing UpdateBoltLightStatus(uid, component); @@ -144,8 +143,8 @@ namespace Content.Server.Doors.Systems private void OnActivate(EntityUid uid, AirlockComponent component, ActivateInWorldEvent args) { - if (TryComp(uid, out var wiresComponent) && wiresComponent.IsPanelOpen && - EntityManager.TryGetComponent(args.User, out ActorComponent? actor)) + if (TryComp(uid, out var panel) && panel.Open && + TryComp(args.User, out var actor)) { _wiresSystem.OpenUserInterface(uid, actor.PlayerSession); args.Handled = true; diff --git a/Content.Server/Mech/Systems/MechSystem.cs b/Content.Server/Mech/Systems/MechSystem.cs index 90a929aaba..ab307673c6 100644 --- a/Content.Server/Mech/Systems/MechSystem.cs +++ b/Content.Server/Mech/Systems/MechSystem.cs @@ -3,7 +3,6 @@ using Content.Server.Atmos.EntitySystems; using Content.Server.DoAfter; using Content.Server.Mech.Components; using Content.Server.Power.Components; -using Content.Server.Wires; using Content.Shared.ActionBlocker; using Content.Shared.Damage; using Content.Shared.DoAfter; @@ -15,6 +14,7 @@ using Content.Shared.Mech.EntitySystems; using Content.Shared.Movement.Events; using Content.Shared.Tools.Components; using Content.Shared.Verbs; +using Content.Shared.Wires; using Robust.Server.Containers; using Robust.Server.GameObjects; using Robust.Shared.Map; @@ -72,7 +72,7 @@ public sealed class MechSystem : SharedMechSystem } private void OnInteractUsing(EntityUid uid, MechComponent component, InteractUsingEvent args) { - if (TryComp(uid, out var wires) && !wires.IsPanelOpen) + if (TryComp(uid, out var panel) && !panel.Open) return; if (component.BatterySlot.ContainedEntity == null && TryComp(args.Used, out var battery)) diff --git a/Content.Server/Power/EntitySystems/ActivatableUIRequiresPowerSystem.cs b/Content.Server/Power/EntitySystems/ActivatableUIRequiresPowerSystem.cs index 828789f535..5f32b4b06b 100644 --- a/Content.Server/Power/EntitySystems/ActivatableUIRequiresPowerSystem.cs +++ b/Content.Server/Power/EntitySystems/ActivatableUIRequiresPowerSystem.cs @@ -1,37 +1,38 @@ using Content.Shared.Popups; using Content.Server.Power.Components; using Content.Server.UserInterface; -using Content.Server.Wires; using JetBrains.Annotations; +using Content.Shared.Wires; -namespace Content.Server.Power.EntitySystems +namespace Content.Server.Power.EntitySystems; + +[UsedImplicitly] +internal sealed class ActivatableUIRequiresPowerSystem : EntitySystem { - [UsedImplicitly] - internal sealed class ActivatableUIRequiresPowerSystem : EntitySystem + [Dependency] private readonly ActivatableUISystem _activatableUI = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; + + public override void Initialize() { - [Dependency] private readonly ActivatableUISystem _activatableUISystem = default!; - public override void Initialize() - { - base.Initialize(); + base.Initialize(); - SubscribeLocalEvent(OnActivate); - SubscribeLocalEvent(OnPowerChanged); - } + SubscribeLocalEvent(OnActivate); + SubscribeLocalEvent(OnPowerChanged); + } - private void OnActivate(EntityUid uid, ActivatableUIRequiresPowerComponent component, ActivatableUIOpenAttemptEvent args) - { - if (args.Cancelled) return; - if (this.IsPowered(uid, EntityManager)) return; - if (TryComp(uid, out var wires) && wires.IsPanelOpen) - return; - args.User.PopupMessageCursor(Loc.GetString("base-computer-ui-component-not-powered", ("machine", uid))); - args.Cancel(); - } + private void OnActivate(EntityUid uid, ActivatableUIRequiresPowerComponent component, ActivatableUIOpenAttemptEvent args) + { + if (args.Cancelled) return; + if (this.IsPowered(uid, EntityManager)) return; + if (TryComp(uid, out var panel) && panel.Open) + return; + _popup.PopupCursor(Loc.GetString("base-computer-ui-component-not-powered", ("machine", uid)), args.User); + args.Cancel(); + } - private void OnPowerChanged(EntityUid uid, ActivatableUIRequiresPowerComponent component, ref PowerChangedEvent args) - { - if (!args.Powered) - _activatableUISystem.CloseAll(uid); - } + private void OnPowerChanged(EntityUid uid, ActivatableUIRequiresPowerComponent component, ref PowerChangedEvent args) + { + if (!args.Powered) + _activatableUI.CloseAll(uid); } } diff --git a/Content.Server/VendingMachines/Restock/VendingMachineRestockSystem.cs b/Content.Server/VendingMachines/Restock/VendingMachineRestockSystem.cs index e8528edadf..39ae673902 100644 --- a/Content.Server/VendingMachines/Restock/VendingMachineRestockSystem.cs +++ b/Content.Server/VendingMachines/Restock/VendingMachineRestockSystem.cs @@ -1,11 +1,11 @@ using System.Linq; using Content.Server.Cargo.Systems; using Content.Server.DoAfter; -using Content.Server.Wires; using Content.Shared.DoAfter; using Content.Shared.Interaction; using Content.Shared.Popups; using Content.Shared.VendingMachines; +using Content.Shared.Wires; using Robust.Server.GameObjects; using Robust.Shared.Audio; using Robust.Shared.Prototypes; @@ -35,7 +35,7 @@ namespace Content.Server.VendingMachines.Restock EntityUid user, EntityUid target) { - if (!TryComp(target, out var wires) || !wires.IsPanelOpen) + if (!TryComp(target, out var panel) || !panel.Open) { _popupSystem.PopupCursor(Loc.GetString("vending-machine-restock-needs-panel-open", ("this", uid), diff --git a/Content.Server/Wires/WiresComponent.cs b/Content.Server/Wires/WiresComponent.cs index 2a96c19c1e..1221e61863 100644 --- a/Content.Server/Wires/WiresComponent.cs +++ b/Content.Server/Wires/WiresComponent.cs @@ -5,18 +5,6 @@ namespace Content.Server.Wires; [RegisterComponent] public sealed class WiresComponent : Component { - /// - /// Is the panel open for this entity's wires? - /// - [ViewVariables] - public bool IsPanelOpen { get; set; } - - /// - /// Should this entity's wires panel be visible at all? - /// - [ViewVariables] - public bool IsPanelVisible { get; set; } = true; - /// /// The name of this entity's internal board. /// @@ -62,13 +50,6 @@ public sealed class WiresComponent : Component [DataField("alwaysRandomize")] public bool AlwaysRandomize { get; } - /// - /// Marks if maintenance panel being open/closed by someone with a screwdriver. - /// Prevents do after spam. - /// - [ViewVariables(VVAccess.ReadWrite)] - public bool IsScrewing; - /// /// Per wire status, keyed by an object. /// @@ -85,10 +66,4 @@ public sealed class WiresComponent : Component [DataField("pulseSound")] public SoundSpecifier PulseSound = new SoundPathSpecifier("/Audio/Effects/multitool_pulse.ogg"); - - [DataField("screwdriverOpenSound")] - public SoundSpecifier ScrewdriverOpenSound = new SoundPathSpecifier("/Audio/Machines/screwdriveropen.ogg"); - - [DataField("screwdriverCloseSound")] - public SoundSpecifier ScrewdriverCloseSound = new SoundPathSpecifier("/Audio/Machines/screwdriverclose.ogg"); } diff --git a/Content.Server/Wires/WiresSystem.cs b/Content.Server/Wires/WiresSystem.cs index 9d6a7c1966..7a3f5f7a05 100644 --- a/Content.Server/Wires/WiresSystem.cs +++ b/Content.Server/Wires/WiresSystem.cs @@ -7,7 +7,6 @@ using Content.Server.Hands.Components; using Content.Server.Power.Components; using Content.Shared.DoAfter; using Content.Shared.Database; -using Content.Shared.Examine; using Content.Shared.GameTicking; using Content.Shared.Interaction; using Content.Shared.Popups; @@ -21,17 +20,17 @@ using Robust.Shared.Random; namespace Content.Server.Wires; -public sealed class WiresSystem : EntitySystem +public sealed class WiresSystem : SharedWiresSystem { [Dependency] private readonly IPrototypeManager _protoMan = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!; - [Dependency] private readonly AppearanceSystem _appearance = default!; [Dependency] private readonly DoAfterSystem _doAfter = default!; [Dependency] private readonly SharedToolSystem _toolSystem = default!; [Dependency] private readonly SharedPopupSystem _popupSystem = default!; [Dependency] private readonly SharedInteractionSystem _interactionSystem = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly UserInterfaceSystem _uiSystem = default!; + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; private IRobustRandom _random = new RobustRandom(); @@ -44,6 +43,8 @@ public sealed class WiresSystem : EntitySystem #region Initialization public override void Initialize() { + base.Initialize(); + SubscribeLocalEvent(Reset); // this is a broadcast event @@ -52,7 +53,6 @@ public sealed class WiresSystem : EntitySystem SubscribeLocalEvent(OnWiresStartup); SubscribeLocalEvent(OnWiresActionMessage); SubscribeLocalEvent(OnInteractUsing); - SubscribeLocalEvent(OnExamine); SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent(OnTimedWire); SubscribeLocalEvent(OnWiresPowered); @@ -244,7 +244,6 @@ public sealed class WiresSystem : EntitySystem SetOrCreateWireLayout(uid, component); UpdateUserInterface(uid); - UpdateAppearance(uid); } #endregion @@ -456,75 +455,71 @@ public sealed class WiresSystem : EntitySystem private void OnInteractUsing(EntityUid uid, WiresComponent component, InteractUsingEvent args) { - if (!EntityManager.TryGetComponent(args.Used, out ToolComponent? tool)) + if (!TryComp(args.Used, out var tool) || !TryComp(uid, out var panel)) return; - - if (component.IsPanelOpen && + if (panel.Open && (_toolSystem.HasQuality(args.Used, "Cutting", tool) || _toolSystem.HasQuality(args.Used, "Pulsing", tool))) { if (EntityManager.TryGetComponent(args.User, out ActorComponent? actor)) { - _uiSystem.GetUiOrNull(uid, WiresUiKey.Key)?.Open(actor.PlayerSession); + var ui = _uiSystem.GetUiOrNull(uid, WiresUiKey.Key); + if (ui != null) + _uiSystem.OpenUi(ui, actor.PlayerSession); args.Handled = true; } } - else if (!component.IsScrewing && _toolSystem.HasQuality(args.Used, "Screwing", tool)) + else if (!panel.IsScrewing && _toolSystem.HasQuality(args.Used, "Screwing", tool)) { var toolEvData = new ToolEventData(new WireToolFinishedEvent(uid, args.User), cancelledEv: new WireToolCanceledEvent(uid)); - component.IsScrewing = _toolSystem.UseTool(args.Used, args.User, uid, ScrewTime, new[] { "Screwing" }, toolEvData, toolComponent: tool); - args.Handled = component.IsScrewing; + panel.IsScrewing = _toolSystem.UseTool(args.Used, args.User, uid, ScrewTime, new[] { "Screwing" }, toolEvData, toolComponent: tool); + args.Handled = panel.IsScrewing; // Log attempt - _adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):user} is screwing {ToPrettyString(uid):target}'s {(component.IsPanelOpen ? "open" : "closed")} maintenance panel at {Transform(uid).Coordinates:targetlocation}"); + _adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):user} is screwing {ToPrettyString(uid):target}'s {(panel.Open ? "open" : "closed")} maintenance panel at {Transform(uid).Coordinates:targetlocation}"); } } private void OnToolFinished(WireToolFinishedEvent args) { - if (!EntityManager.TryGetComponent(args.Target, out WiresComponent? component)) + if (!TryComp((args.Target), out var panel)) return; - component.IsScrewing = false; - component.IsPanelOpen = !component.IsPanelOpen; - UpdateAppearance(args.Target); + panel.IsScrewing = false; + TogglePanel(args.Target, panel, !panel.Open); // Log success - _adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):user} screwed {ToPrettyString(args.Target):target}'s maintenance panel {(component.IsPanelOpen ? "open" : "closed")}"); + _adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(args.User):user} screwed {ToPrettyString(args.Target):target}'s maintenance panel {(panel.Open ? "open" : "closed")}"); - if (component.IsPanelOpen) + if (panel.Open) { - _audio.PlayPvs(component.ScrewdriverOpenSound, args.Target); + _audio.PlayPvs(panel.ScrewdriverOpenSound, args.Target); } else { - _audio.PlayPvs(component.ScrewdriverCloseSound, args.Target); + _audio.PlayPvs(panel.ScrewdriverCloseSound, args.Target); var ui = _uiSystem.GetUiOrNull(args.Target, WiresUiKey.Key); if (ui != null) { _uiSystem.CloseAll(ui); } } + + Dirty(panel); } private void OnToolCanceled(WireToolCanceledEvent ev) { - if (!TryComp(ev.Target, out WiresComponent? component)) + if (!TryComp(ev.Target, out var component)) return; component.IsScrewing = false; } - private void OnExamine(EntityUid uid, WiresComponent component, ExaminedEvent args) - { - args.PushMarkup(Loc.GetString(component.IsPanelOpen - ? "wires-component-on-examine-panel-open" - : "wires-component-on-examine-panel-closed")); - } - private void OnMapInit(EntityUid uid, WiresComponent component, MapInitEvent args) { + EnsureComp(uid); if (component.SerialNumber == null) { GenerateSerialNumber(uid, component); @@ -574,14 +569,6 @@ public sealed class WiresSystem : EntitySystem UpdateUserInterface(uid); } - private void UpdateAppearance(EntityUid uid, AppearanceComponent? appearance = null, WiresComponent? wires = null) - { - if (!Resolve(uid, ref appearance, ref wires, false)) - return; - - _appearance.SetData(uid, WiresVisuals.MaintenancePanelState, wires.IsPanelOpen && wires.IsPanelVisible, appearance); - } - private void UpdateUserInterface(EntityUid uid, WiresComponent? wires = null, ServerUserInterfaceComponent? ui = null) { if (!Resolve(uid, ref wires, ref ui, false)) // logging this means that we get a bunch of errors @@ -655,6 +642,26 @@ public sealed class WiresSystem : EntitySystem } } + public void ChangePanelVisibility(EntityUid uid, WiresPanelComponent component, bool visible) + { + component.Visible = visible; + UpdateAppearance(uid, component); + Dirty(component); + } + + public void TogglePanel(EntityUid uid, WiresPanelComponent component, bool open) + { + component.Open = open; + UpdateAppearance(uid, component); + Dirty(component); + } + + private void UpdateAppearance(EntityUid uid, WiresPanelComponent panel) + { + if (TryComp(uid, out var appearance)) + _appearance.SetData(uid, WiresVisuals.MaintenancePanelState, panel.Open && panel.Visible, appearance); + } + private void TryDoWireAction(EntityUid used, EntityUid user, EntityUid toolEntity, int id, WiresAction action, WiresComponent? wires = null, ToolComponent? tool = null) { if (!Resolve(used, ref wires) @@ -720,7 +727,7 @@ public sealed class WiresSystem : EntitySystem if (_toolTime > 0f) { var data = new WireExtraData(action, id); - var args = new DoAfterEventArgs(user, _toolTime, target:used, used:toolEntity) + var args = new DoAfterEventArgs(user, _toolTime, target: used, used: toolEntity) { NeedHand = true, BreakOnStun = true, diff --git a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs index 1ecf2a9794..cb10ec07f2 100644 --- a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs +++ b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs @@ -7,7 +7,9 @@ using Content.Shared.Popups; using Content.Shared.Radio.Components; using Content.Shared.Tools; using Content.Shared.Tools.Components; +using Content.Shared.Wires; using Robust.Shared.Containers; +using Robust.Shared.Network; using Robust.Shared.Prototypes; using Robust.Shared.Timing; @@ -20,8 +22,9 @@ public sealed class EncryptionKeySystem : EntitySystem { [Dependency] private readonly IPrototypeManager _protoManager = default!; [Dependency] private readonly IGameTiming _timing = default!; - [Dependency] private readonly SharedToolSystem _toolSystem = default!; - [Dependency] private readonly SharedPopupSystem _popupSystem = default!; + [Dependency] private readonly INetManager _net = default!; + [Dependency] private readonly SharedToolSystem _tool = default!; + [Dependency] private readonly SharedPopupSystem _popup = default!; [Dependency] private readonly SharedContainerSystem _container = default!; [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly SharedHandsSystem _hands = default!; @@ -55,7 +58,7 @@ public sealed class EncryptionKeySystem : EntitySystem } // if tool use ever gets predicted this needs changing. - _popupSystem.PopupEntity(Loc.GetString("encryption-keys-all-extracted"), uid, args.User); + _popup.PopupEntity(Loc.GetString("encryption-keys-all-extracted"), uid, args.User); _audio.PlayPvs(component.KeyExtractionSound, uid); component.Removing = false; } @@ -92,8 +95,8 @@ public sealed class EncryptionKeySystem : EntitySystem return; if (!component.KeysUnlocked) { - if (_timing.IsFirstTimePredicted) - _popupSystem.PopupEntity(Loc.GetString("encryption-keys-are-locked"), uid, args.User); + if (_net.IsClient && _timing.IsFirstTimePredicted) + _popup.PopupEntity(Loc.GetString("encryption-keys-are-locked"), uid, args.User); return; } if (TryComp(args.Used, out var key)) @@ -108,20 +111,26 @@ public sealed class EncryptionKeySystem : EntitySystem private void TryInsertKey(EntityUid uid, EncryptionKeyHolderComponent component, InteractUsingEvent args) { - args.Handled = true; + if (TryComp(uid, out var panel) && !panel.Open) + { + if (_net.IsClient && _timing.IsFirstTimePredicted) + _popup.PopupEntity(Loc.GetString("encryption-keys-panel-locked"), uid, args.User); + return; + } if (component.KeySlots <= component.KeyContainer.ContainedEntities.Count) { - if (_timing.IsFirstTimePredicted) - _popupSystem.PopupEntity(Loc.GetString("encryption-key-slots-already-full"), uid, args.User); + if (_net.IsClient && _timing.IsFirstTimePredicted) + _popup.PopupEntity(Loc.GetString("encryption-key-slots-already-full"), uid, args.User); return; } if (component.KeyContainer.Insert(args.Used)) { - if (_timing.IsFirstTimePredicted) - _popupSystem.PopupEntity(Loc.GetString("encryption-key-successfully-installed"), uid, args.User); + if (_net.IsClient&& _timing.IsFirstTimePredicted) + _popup.PopupEntity(Loc.GetString("encryption-key-successfully-installed"), uid, args.User); _audio.PlayPredicted(component.KeyInsertionSound, args.Target, args.User); + args.Handled = true; return; } } @@ -131,21 +140,28 @@ public sealed class EncryptionKeySystem : EntitySystem if (!TryComp(args.Used, out var tool) || !tool.Qualities.Contains(component.KeysExtractionMethod)) return; - args.Handled = true; - - if (component.KeyContainer.ContainedEntities.Count == 0) + if (TryComp(uid, out var panel) && !panel.Open) { - if (_timing.IsFirstTimePredicted) - _popupSystem.PopupEntity(Loc.GetString("encryption-keys-no-keys"), uid, args.User); + if (_net.IsClient && _timing.IsFirstTimePredicted) + _popup.PopupEntity(Loc.GetString("encryption-keys-panel-locked"), uid, args.User); return; } - //This is honestly the poor mans fix because the InteractUsingEvent fires off 12 times - component.Removing = true; + if (component.KeyContainer.ContainedEntities.Count == 0) + { + if (_net.IsClient && _timing.IsFirstTimePredicted) + _popup.PopupEntity(Loc.GetString("encryption-keys-no-keys"), uid, args.User); + return; + } - var toolEvData = new ToolEventData(new EncryptionRemovalFinishedEvent(args.User), cancelledEv: new EncryptionRemovalCancelledEvent(), targetEntity: uid); - - _toolSystem.UseTool(args.Used, args.User, uid, 1f, new[] { component.KeysExtractionMethod }, toolEvData, toolComponent: tool); + if (_net.IsServer) + { + //This is honestly the poor mans fix because the InteractUsingEvent fires off 12 times + component.Removing = true; + var toolEvData = new ToolEventData(new EncryptionRemovalFinishedEvent(args.User), cancelledEv: new EncryptionRemovalCancelledEvent(), targetEntity: uid); + if (_tool.UseTool(args.Used, args.User, uid, 1f, new[] { component.KeysExtractionMethod }, toolEvData, toolComponent: tool)) + args.Handled = true; + } } private void OnStartup(EntityUid uid, EncryptionKeyHolderComponent component, ComponentStartup args) diff --git a/Content.Shared/Wires/SharedWiresSystem.cs b/Content.Shared/Wires/SharedWiresSystem.cs new file mode 100644 index 0000000000..d7ddac4de2 --- /dev/null +++ b/Content.Shared/Wires/SharedWiresSystem.cs @@ -0,0 +1,39 @@ +using Content.Shared.Examine; +using Robust.Shared.GameStates; + +namespace Content.Shared.Wires; + +public abstract class SharedWiresSystem : EntitySystem +{ + public override void Initialize() + { + base.Initialize(); + SubscribeLocalEvent(OnExamine); + SubscribeLocalEvent(OnGetState); + SubscribeLocalEvent(OnHandleState); + } + + private void OnExamine(EntityUid uid, WiresPanelComponent component, ExaminedEvent args) + { + args.PushMarkup(Loc.GetString(component.Open + ? "wires-panel-component-on-examine-open" + : "wires-panel-component-on-examine-closed")); + } + + private void OnGetState(EntityUid uid, WiresPanelComponent component, ref ComponentGetState args) + { + args.State = new WiresPanelComponentState + { + Open = component.Open, + Visible = component.Visible + }; + } + + private void OnHandleState(EntityUid uid, WiresPanelComponent component, ref ComponentHandleState args) + { + if (args.Current is not WiresPanelComponentState state) + return; + component.Open = state.Open; + component.Visible = state.Visible; + } +} \ No newline at end of file diff --git a/Content.Shared/Wires/WiresPanelComponent.cs b/Content.Shared/Wires/WiresPanelComponent.cs new file mode 100644 index 0000000000..a1519b6325 --- /dev/null +++ b/Content.Shared/Wires/WiresPanelComponent.cs @@ -0,0 +1,41 @@ +using Robust.Shared.Audio; +using Robust.Shared.GameStates; +using Robust.Shared.Serialization; + +namespace Content.Shared.Wires; + +[NetworkedComponent, RegisterComponent] +[Access(typeof(SharedWiresSystem))] +public sealed class WiresPanelComponent : Component +{ + /// + /// Is the panel open for this entity's wires? + /// + [ViewVariables] + public bool Open; + + /// + /// Should this entity's wires panel be visible at all? + /// + [ViewVariables] + public bool Visible = true; + + /// + /// Marks if maintenance panel being open/closed by someone with a screwdriver. + /// Prevents do after spam. + /// + public bool IsScrewing; + + [DataField("screwdriverOpenSound")] + public SoundSpecifier ScrewdriverOpenSound = new SoundPathSpecifier("/Audio/Machines/screwdriveropen.ogg"); + + [DataField("screwdriverCloseSound")] + public SoundSpecifier ScrewdriverCloseSound = new SoundPathSpecifier("/Audio/Machines/screwdriverclose.ogg"); +} + +[Serializable, NetSerializable] +public sealed class WiresPanelComponentState : ComponentState +{ + public bool Open; + public bool Visible; +} diff --git a/Resources/Locale/en-US/radio/components/encryption-key-component.ftl b/Resources/Locale/en-US/radio/components/encryption-key-component.ftl index 6d9dc5261c..d595cd3790 100644 --- a/Resources/Locale/en-US/radio/components/encryption-key-component.ftl +++ b/Resources/Locale/en-US/radio/components/encryption-key-component.ftl @@ -3,6 +3,7 @@ encryption-key-slots-already-full = There is no place for another encryption key encryption-keys-all-extracted = You pop out the encryption keys! encryption-keys-no-keys = This device has no encryption keys! encryption-keys-are-locked = Encryption key slots are locked! +encryption-keys-panel-locked = Open maintenance panel first! examine-encryption-channels-prefix = Available frequencies: examine-encryption-channel = [color={$color}]{$key} for {$id} ({$freq})[/color] diff --git a/Resources/Locale/en-US/wires/components/wires-component.ftl b/Resources/Locale/en-US/wires/components/wires-component.ftl index 496a0d0f6a..be27c270bb 100644 --- a/Resources/Locale/en-US/wires/components/wires-component.ftl +++ b/Resources/Locale/en-US/wires/components/wires-component.ftl @@ -5,8 +5,6 @@ wires-component-ui-on-receive-message-need-multitool = You need to hold a multit wires-component-ui-on-receive-message-cannot-pulse-cut-wire = You can't pulse a wire that's been cut! wires-component-ui-on-receive-message-cannot-cut-cut-wire = You can't cut a wire that's been cut! wires-component-ui-on-receive-message-cannot-mend-uncut-wire = You can't mend a wire that's been mended! -wires-component-on-examine-panel-open = The [color=lightgray]maintenance panel[/color] is [color=red]open[/color]. -wires-component-on-examine-panel-closed = The [color=lightgray]maintenance panel[/color] is [color=darkgreen]closed[/color]. ## UI diff --git a/Resources/Locale/en-US/wires/components/wires-panel-component.ftl b/Resources/Locale/en-US/wires/components/wires-panel-component.ftl new file mode 100644 index 0000000000..cd8867f135 --- /dev/null +++ b/Resources/Locale/en-US/wires/components/wires-panel-component.ftl @@ -0,0 +1,2 @@ +wires-panel-component-on-examine-open = The [color=lightgray]maintenance panel[/color] is [color=red]open[/color]. +wires-panel-component-on-examine-closed = The [color=lightgray]maintenance panel[/color] is [color=darkgreen]closed[/color].