diff --git a/Content.Server/DeviceLinking/Components/SignalSwitchComponent.cs b/Content.Server/DeviceLinking/Components/SignalSwitchComponent.cs index 4259ba6c6c..5dc1d69aeb 100644 --- a/Content.Server/DeviceLinking/Components/SignalSwitchComponent.cs +++ b/Content.Server/DeviceLinking/Components/SignalSwitchComponent.cs @@ -1,32 +1,39 @@ +using Content.Server.DeviceLinking.Systems; using Content.Shared.MachineLinking; using Robust.Shared.Audio; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -namespace Content.Server.DeviceLinking.Components +namespace Content.Server.DeviceLinking.Components; + +/// +/// Simple switch that will fire ports when toggled on or off. A button is jsut a switch that signals on the +/// same port regardless of its state. +/// +[RegisterComponent, Access(typeof(SignalSwitchSystem))] +public sealed class SignalSwitchComponent : Component { /// - /// Simple switch that will fire ports when toggled on or off. A button is jsut a switch that signals on the - /// same port regardless of its state. + /// The port that gets signaled when the switch turns on. /// - [RegisterComponent] - public sealed class SignalSwitchComponent : Component - { - /// - /// The port that gets signaled when the switch turns on. - /// - [DataField("onPort", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string OnPort = "On"; + [DataField("onPort", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string OnPort = "On"; - /// - /// The port that gets signaled when the switch turns off. - /// - [DataField("offPort", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string OffPort = "Off"; + /// + /// The port that gets signaled when the switch turns off. + /// + [DataField("offPort", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string OffPort = "Off"; - [DataField("state")] - public bool State; + /// + /// The port that gets signaled with the switch's current status. + /// This is only used if OnPort is different from OffPort, not in the case of a toggle switch. + /// + [DataField("statusPort", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string StatusPort = "Status"; - [DataField("clickSound")] - public SoundSpecifier ClickSound { get; set; } = new SoundPathSpecifier("/Audio/Machines/lightswitch.ogg"); - } + [DataField("state")] + public bool State; + + [DataField("clickSound")] + public SoundSpecifier ClickSound = new SoundPathSpecifier("/Audio/Machines/lightswitch.ogg"); } diff --git a/Content.Server/DeviceLinking/Systems/LogicGateSystem.cs b/Content.Server/DeviceLinking/Systems/LogicGateSystem.cs index 70e9ede1f2..b32f5694a2 100644 --- a/Content.Server/DeviceLinking/Systems/LogicGateSystem.cs +++ b/Content.Server/DeviceLinking/Systems/LogicGateSystem.cs @@ -32,6 +32,26 @@ public sealed class LogicGateSystem : EntitySystem SubscribeLocalEvent(OnSignalReceived); } + public override void Update(float deltaTime) + { + var query = EntityQueryEnumerator(); + while (query.MoveNext(out var uid, out var comp)) + { + // handle momentary pulses - high when received then low the next tick + if (comp.StateA == SignalState.Momentary) + { + comp.StateA = SignalState.Low; + } + if (comp.StateB == SignalState.Momentary) + { + comp.StateB = SignalState.High; + } + + // output most likely changed so update it + UpdateOutput(uid, comp); + } + } + private void OnInit(EntityUid uid, LogicGateComponent comp, ComponentInit args) { _deviceLink.EnsureSinkPorts(uid, comp.InputPortA, comp.InputPortB); @@ -92,8 +112,9 @@ public sealed class LogicGateSystem : EntitySystem private void UpdateOutput(EntityUid uid, LogicGateComponent comp) { // get the new output value now that it's changed - var a = comp.StateA == SignalState.High; - var b = comp.StateB == SignalState.High; + // momentary is treated as high for the current tick, after updating it will be reset to low + var a = comp.StateA != SignalState.Low; + var b = comp.StateB != SignalState.Low; var output = false; switch (comp.Gate) { diff --git a/Content.Server/DeviceLinking/Systems/SignalSwitchSystem.cs b/Content.Server/DeviceLinking/Systems/SignalSwitchSystem.cs index acb3acb4aa..8e70aad706 100644 --- a/Content.Server/DeviceLinking/Systems/SignalSwitchSystem.cs +++ b/Content.Server/DeviceLinking/Systems/SignalSwitchSystem.cs @@ -1,40 +1,51 @@ using Content.Server.DeviceLinking.Components; +using Content.Server.DeviceNetwork; using Content.Server.MachineLinking.System; using Content.Shared.Audio; using Content.Shared.Interaction; using Robust.Shared.Audio; using Robust.Shared.Player; -namespace Content.Server.DeviceLinking.Systems +namespace Content.Server.DeviceLinking.Systems; + +public sealed class SignalSwitchSystem : EntitySystem { - public sealed class SignalSwitchSystem : EntitySystem + [Dependency] private readonly DeviceLinkSystem _deviceLink = default!; + [Dependency] private readonly SharedAudioSystem _audio = default!; + + public override void Initialize() { - [Dependency] private readonly DeviceLinkSystem _signalSystem = default!; + base.Initialize(); - public override void Initialize() + SubscribeLocalEvent(OnInit); + SubscribeLocalEvent(OnActivated); + } + + private void OnInit(EntityUid uid, SignalSwitchComponent comp, ComponentInit args) + { + _deviceLink.EnsureSourcePorts(uid, comp.OnPort, comp.OffPort, comp.StatusPort); + } + + private void OnActivated(EntityUid uid, SignalSwitchComponent comp, ActivateInWorldEvent args) + { + if (args.Handled) + return; + + comp.State = !comp.State; + _deviceLink.InvokePort(uid, comp.State ? comp.OnPort : comp.OffPort); + var data = new NetworkPayload { - base.Initialize(); + [DeviceNetworkConstants.LogicState] = comp.State ? SignalState.High : SignalState.Low + }; - SubscribeLocalEvent(OnInit); - SubscribeLocalEvent(OnActivated); + // only send status if it's a toggle switch and not a button + if (comp.OnPort != comp.OffPort) + { + _deviceLink.InvokePort(uid, comp.StatusPort, data); } - private void OnInit(EntityUid uid, SignalSwitchComponent component, ComponentInit args) - { - _signalSystem.EnsureSourcePorts(uid, component.OnPort, component.OffPort); - } + _audio.PlayPvs(comp.ClickSound, uid, AudioParams.Default.WithVariation(0.125f).WithVolume(8f)); - private void OnActivated(EntityUid uid, SignalSwitchComponent component, ActivateInWorldEvent args) - { - if (args.Handled) - return; - - component.State = !component.State; - _signalSystem.InvokePort(uid, component.State ? component.OnPort : component.OffPort); - SoundSystem.Play(component.ClickSound.GetSound(), Filter.Pvs(component.Owner), component.Owner, - AudioHelpers.WithVariation(0.125f).WithVolume(8f)); - - args.Handled = true; - } + args.Handled = true; } } diff --git a/Resources/Locale/en-US/machine-linking/transmitter_ports.ftl b/Resources/Locale/en-US/machine-linking/transmitter_ports.ftl index 909c0dae87..02ede1e1b6 100644 --- a/Resources/Locale/en-US/machine-linking/transmitter_ports.ftl +++ b/Resources/Locale/en-US/machine-linking/transmitter_ports.ftl @@ -7,6 +7,9 @@ signal-port-description-on-transmitter = This port is invoked whenever the trans signal-port-name-off-transmitter = Off signal-port-description-off-transmitter = This port is invoked whenever the transmitter is turned off. +signal-port-name-status-transmitter = Status +signal-port-description-logic-output = This port is invoked with HIGH or LOW depending on the transmitter status. + signal-port-name-left = Left signal-port-description-left = This port is invoked whenever the lever is moved to the leftmost position. @@ -14,7 +17,7 @@ signal-port-name-right = Right signal-port-description-right = This port is invoked whenever the lever is moved to the rightmost position. signal-port-name-doorstatus = Door status -signal-port-description-doorstatus = This port is invoked with HIGH when the door opens and LOW when the door closes. +signal-port-description-doorstatus = This port is invoked with HIGH when the door opens and LOW when the door finishes closing. signal-port-name-middle = Middle signal-port-description-middle = This port is invoked whenever the lever is moved to the neutral position. diff --git a/Resources/Prototypes/DeviceLinking/source_ports.yml b/Resources/Prototypes/DeviceLinking/source_ports.yml index 151ba9c26f..45ee812f2e 100644 --- a/Resources/Prototypes/DeviceLinking/source_ports.yml +++ b/Resources/Prototypes/DeviceLinking/source_ports.yml @@ -16,6 +16,11 @@ description: signal-port-description-off-transmitter defaultLinks: [ Off, Close ] +- type: sourcePort + id: Status + name: signal-port-name-status-transmitter + description: signal-port-description-status-transmitter + - type: sourcePort id: Left name: signal-port-name-left @@ -78,13 +83,16 @@ id: Output name: signal-port-name-logic-output description: signal-port-description-logic-output + defaultLinks: [ Input ] - type: sourcePort id: OutputHigh name: signal-port-name-logic-output-high description: signal-port-description-logic-output-high + defaultLinks: [ On, Open, Forward, Trigger ] - type: sourcePort id: OutputLow name: signal-port-name-logic-output-low description: signal-port-description-logic-output-low + defaultLinks: [ Off, Close ] diff --git a/Resources/Prototypes/Entities/Structures/Wallmounts/switch.yml b/Resources/Prototypes/Entities/Structures/Wallmounts/switch.yml index db6825b96e..012870a56e 100644 --- a/Resources/Prototypes/Entities/Structures/Wallmounts/switch.yml +++ b/Resources/Prototypes/Entities/Structures/Wallmounts/switch.yml @@ -30,8 +30,9 @@ range: 200 - type: DeviceLinkSource ports: - - On - - Off + - On + - Off + - Status - type: entity id: SignalButton @@ -56,6 +57,7 @@ - type: SignalSwitch onPort: Pressed offPort: Pressed + statusPort: Pressed - type: Rotatable - type: Construction graph: SignalButtonGraph diff --git a/Resources/Prototypes/MachineLinking/transmitter_ports.yml b/Resources/Prototypes/MachineLinking/transmitter_ports.yml index 4949097134..c97b324652 100644 --- a/Resources/Prototypes/MachineLinking/transmitter_ports.yml +++ b/Resources/Prototypes/MachineLinking/transmitter_ports.yml @@ -16,6 +16,11 @@ description: signal-port-description-off-transmitter defaultLinks: [ Off, Close ] +- type: transmitterPort + id: Status + name: signal-port-name-status-transmitter + description: signal-port-description-status-transmitter + - type: transmitterPort id: Left name: signal-port-name-left @@ -78,13 +83,16 @@ id: Output name: signal-port-name-logic-output description: signal-port-description-logic-output + defaultLinks: [ Input ] - type: transmitterPort id: OutputHigh name: signal-port-name-logic-output-high description: signal-port-description-logic-output-high + defaultLinks: [ On, Open, Forward, Trigger ] - type: transmitterPort id: OutputLow name: signal-port-name-logic-output-low description: signal-port-description-logic-output-low + defaultLinks: [ Off, Close ]