diff --git a/Content.Client/Radio/EntitySystems/RadioDeviceSystem.cs b/Content.Client/Radio/EntitySystems/RadioDeviceSystem.cs index 29d6c635eb..a2711a8257 100644 --- a/Content.Client/Radio/EntitySystems/RadioDeviceSystem.cs +++ b/Content.Client/Radio/EntitySystems/RadioDeviceSystem.cs @@ -1,11 +1,12 @@ using Content.Client.Radio.Ui; using Content.Shared.Radio; using Content.Shared.Radio.Components; +using Content.Shared.Radio.EntitySystems; using Robust.Client.GameObjects; namespace Content.Client.Radio.EntitySystems; -public sealed class RadioDeviceSystem : EntitySystem +public sealed class RadioDeviceSystem : SharedRadioDeviceSystem { [Dependency] private readonly UserInterfaceSystem _ui = default!; diff --git a/Content.Client/Silicons/Laws/Ui/LawDisplay.xaml.cs b/Content.Client/Silicons/Laws/Ui/LawDisplay.xaml.cs index 245ea194f0..55fb99a526 100644 --- a/Content.Client/Silicons/Laws/Ui/LawDisplay.xaml.cs +++ b/Content.Client/Silicons/Laws/Ui/LawDisplay.xaml.cs @@ -26,7 +26,7 @@ public sealed partial class LawDisplay : Control private readonly Dictionary _nextAllowedPress = new(); - public LawDisplay(EntityUid uid, SiliconLaw law, HashSet? radioChannels) + public LawDisplay(EntityUid uid, SiliconLaw law, HashSet>? radioChannels) { RobustXamlLoader.Load(this); IoCManager.InjectDependencies(this); diff --git a/Content.Server/Implants/RadioImplantSystem.cs b/Content.Server/Implants/RadioImplantSystem.cs index c5ae1ce494..db713e92b3 100644 --- a/Content.Server/Implants/RadioImplantSystem.cs +++ b/Content.Server/Implants/RadioImplantSystem.cs @@ -1,6 +1,6 @@ -using Content.Server.Radio.Components; -using Content.Shared.Implants; +using Content.Shared.Implants; using Content.Shared.Implants.Components; +using Content.Shared.Radio.Components; namespace Content.Server.Implants; diff --git a/Content.Server/Radio/Components/IntrinsicRadioTransmitterComponent.cs b/Content.Server/Radio/Components/IntrinsicRadioTransmitterComponent.cs deleted file mode 100644 index 13cc090663..0000000000 --- a/Content.Server/Radio/Components/IntrinsicRadioTransmitterComponent.cs +++ /dev/null @@ -1,17 +0,0 @@ -using Content.Server.Chat.Systems; -using Content.Shared.Chat; -using Content.Shared.Radio; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set; - -namespace Content.Server.Radio.Components; - -/// -/// This component allows an entity to directly translate spoken text into radio messages (effectively an intrinsic -/// radio headset). -/// -[RegisterComponent] -public sealed partial class IntrinsicRadioTransmitterComponent : Component -{ - [DataField("channels", customTypeSerializer: typeof(PrototypeIdHashSetSerializer))] - public HashSet Channels = new() { SharedChatSystem.CommonChannel }; -} diff --git a/Content.Server/Radio/Components/RadioMicrophoneComponent.cs b/Content.Server/Radio/Components/RadioMicrophoneComponent.cs deleted file mode 100644 index af01f86f23..0000000000 --- a/Content.Server/Radio/Components/RadioMicrophoneComponent.cs +++ /dev/null @@ -1,43 +0,0 @@ -using Content.Server.Radio.EntitySystems; -using Content.Shared.Chat; -using Content.Shared.Radio; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; - -namespace Content.Server.Radio.Components; - -/// -/// Listens for local chat messages and relays them to some radio frequency -/// -[RegisterComponent] -[Access(typeof(RadioDeviceSystem))] -public sealed partial class RadioMicrophoneComponent : Component -{ - [ViewVariables(VVAccess.ReadWrite)] - [DataField("broadcastChannel", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string BroadcastChannel = SharedChatSystem.CommonChannel; - - [ViewVariables(VVAccess.ReadWrite)] - [DataField("listenRange")] - public int ListenRange = 4; - - [DataField("enabled")] - public bool Enabled = false; - - [DataField("powerRequired")] - public bool PowerRequired = false; - - /// - /// Whether or not interacting with this entity - /// toggles it on or off. - /// - [DataField("toggleOnInteract")] - public bool ToggleOnInteract = true; - - /// - /// Whether or not the speaker must have an - /// unobstructed path to the radio to speak - /// - [DataField("unobstructedRequired")] - public bool UnobstructedRequired = false; -} diff --git a/Content.Server/Radio/Components/RadioSpeakerComponent.cs b/Content.Server/Radio/Components/RadioSpeakerComponent.cs deleted file mode 100644 index 150e903e52..0000000000 --- a/Content.Server/Radio/Components/RadioSpeakerComponent.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Content.Server.Radio.EntitySystems; -using Content.Shared.Chat; -using Content.Shared.Radio; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set; - -namespace Content.Server.Radio.Components; - -/// -/// Listens for radio messages and relays them to local chat. -/// -[RegisterComponent] -[Access(typeof(RadioDeviceSystem))] -public sealed partial class RadioSpeakerComponent : Component -{ - /// - /// Whether or not interacting with this entity - /// toggles it on or off. - /// - [DataField("toggleOnInteract")] - public bool ToggleOnInteract = true; - - [DataField("channels", customTypeSerializer: typeof(PrototypeIdHashSetSerializer))] - public HashSet Channels = new () { SharedChatSystem.CommonChannel }; - - [DataField("enabled")] - public bool Enabled; -} diff --git a/Content.Server/Radio/EntitySystems/HeadsetSystem.cs b/Content.Server/Radio/EntitySystems/HeadsetSystem.cs index e3f8070311..91abc9efd5 100644 --- a/Content.Server/Radio/EntitySystems/HeadsetSystem.cs +++ b/Content.Server/Radio/EntitySystems/HeadsetSystem.cs @@ -1,6 +1,5 @@ using Content.Server.Chat.Systems; using Content.Server.Emp; -using Content.Server.Radio.Components; using Content.Shared.Inventory.Events; using Content.Shared.Radio; using Content.Shared.Radio.Components; diff --git a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs index f052c460f5..b0f38c92fa 100644 --- a/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs @@ -3,7 +3,7 @@ using Content.Server.Chat.Systems; using Content.Server.Interaction; using Content.Server.Popups; using Content.Server.Power.EntitySystems; -using Content.Server.Radio.Components; +using Content.Shared.Radio.Components; using Content.Shared.Examine; using Content.Shared.Interaction; using Content.Shared.Power; @@ -11,15 +11,15 @@ using Content.Shared.Radio; using Content.Shared.Speech; using Content.Shared.Speech.Components; using Content.Shared.Chat; -using Content.Shared.Radio.Components; using Robust.Shared.Prototypes; +using Content.Shared.Radio.EntitySystems; namespace Content.Server.Radio.EntitySystems; /// /// This system handles radio speakers and microphones (which together form a hand-held radio). /// -public sealed class RadioDeviceSystem : EntitySystem +public sealed class RadioDeviceSystem : SharedRadioDeviceSystem { [Dependency] private readonly IPrototypeManager _protoMan = default!; [Dependency] private readonly PopupSystem _popup = default!; @@ -100,15 +100,6 @@ public sealed class RadioDeviceSystem : EntitySystem ToggleRadioSpeaker(uid, args.User, args.Handled, component); args.Handled = true; } - - public void ToggleRadioMicrophone(EntityUid uid, EntityUid user, bool quiet = false, RadioMicrophoneComponent? component = null) - { - if (!Resolve(uid, ref component)) - return; - - SetMicrophoneEnabled(uid, user, !component.Enabled, quiet, component); - } - private void OnPowerChanged(EntityUid uid, RadioMicrophoneComponent component, ref PowerChangedEvent args) { if (args.Powered) @@ -116,7 +107,8 @@ public sealed class RadioDeviceSystem : EntitySystem SetMicrophoneEnabled(uid, null, false, true, component); } - public void SetMicrophoneEnabled(EntityUid uid, EntityUid? user, bool enabled, bool quiet = false, RadioMicrophoneComponent? component = null) + + public override void SetMicrophoneEnabled(EntityUid uid, EntityUid? user, bool enabled, bool quiet = false, RadioMicrophoneComponent? component = null) { if (!Resolve(uid, ref component, false)) return; @@ -140,34 +132,6 @@ public sealed class RadioDeviceSystem : EntitySystem RemCompDeferred(uid); } - public void ToggleRadioSpeaker(EntityUid uid, EntityUid user, bool quiet = false, RadioSpeakerComponent? component = null) - { - if (!Resolve(uid, ref component)) - return; - - SetSpeakerEnabled(uid, user, !component.Enabled, quiet, component); - } - - public void SetSpeakerEnabled(EntityUid uid, EntityUid? user, bool enabled, bool quiet = false, RadioSpeakerComponent? component = null) - { - if (!Resolve(uid, ref component)) - return; - - component.Enabled = enabled; - - if (!quiet && user != null) - { - var state = Loc.GetString(component.Enabled ? "handheld-radio-component-on-state" : "handheld-radio-component-off-state"); - var message = Loc.GetString("handheld-radio-component-on-use", ("radioState", state)); - _popup.PopupEntity(message, user.Value, user.Value); - } - - _appearance.SetData(uid, RadioDeviceVisuals.Speaker, component.Enabled); - if (component.Enabled) - EnsureComp(uid).Channels.UnionWith(component.Channels); - else - RemCompDeferred(uid); - } #endregion private void OnExamine(EntityUid uid, RadioMicrophoneComponent component, ExaminedEvent args) @@ -277,9 +241,9 @@ public sealed class RadioDeviceSystem : EntitySystem } if (TryComp(ent, out var mic)) - mic.BroadcastChannel = channel; + mic.BroadcastChannel = channel.Value; if (TryComp(ent, out var speaker)) - speaker.Channels = new() { channel }; + speaker.Channels = new() { channel.Value }; Dirty(ent); } } diff --git a/Content.Server/Radio/EntitySystems/RadioSystem.cs b/Content.Server/Radio/EntitySystems/RadioSystem.cs index 6af52b980f..740e6b1030 100644 --- a/Content.Server/Radio/EntitySystems/RadioSystem.cs +++ b/Content.Server/Radio/EntitySystems/RadioSystem.cs @@ -1,7 +1,6 @@ using Content.Server.Administration.Logs; using Content.Server.Chat.Systems; using Content.Server.Power.Components; -using Content.Server.Radio.Components; using Content.Shared.Chat; using Content.Shared.Database; using Content.Shared.Radio; diff --git a/Content.Server/Silicons/Borgs/BorgSwitchableTypeSystem.cs b/Content.Server/Silicons/Borgs/BorgSwitchableTypeSystem.cs index e90acf1b80..b593311840 100644 --- a/Content.Server/Silicons/Borgs/BorgSwitchableTypeSystem.cs +++ b/Content.Server/Silicons/Borgs/BorgSwitchableTypeSystem.cs @@ -1,6 +1,6 @@ using Content.Server.Inventory; -using Content.Server.Radio.Components; using Content.Shared.Inventory; +using Content.Shared.Radio.Components; using Content.Shared.Silicons.Borgs; using Content.Shared.Silicons.Borgs.Components; using Robust.Shared.Prototypes; diff --git a/Content.Server/Silicons/Laws/SiliconLawSystem.cs b/Content.Server/Silicons/Laws/SiliconLawSystem.cs index 653ed6bac2..79b51f2221 100644 --- a/Content.Server/Silicons/Laws/SiliconLawSystem.cs +++ b/Content.Server/Silicons/Laws/SiliconLawSystem.cs @@ -1,7 +1,6 @@ using System.Linq; using Content.Server.Administration; using Content.Server.Chat.Managers; -using Content.Server.Radio.Components; using Content.Server.Station.Systems; using Content.Shared.Administration; using Content.Shared.Chat; @@ -9,6 +8,7 @@ using Content.Shared.Emag.Systems; using Content.Shared.GameTicking; using Content.Shared.Mind; using Content.Shared.Mind.Components; +using Content.Shared.Radio.Components; using Content.Shared.Roles; using Content.Shared.Roles.Components; using Content.Shared.Silicons.Laws; diff --git a/Content.Server/Speech/Components/ListenWireAction.cs b/Content.Server/Speech/Components/ListenWireAction.cs index b8b1c19e84..f9f1d9e92e 100644 --- a/Content.Server/Speech/Components/ListenWireAction.cs +++ b/Content.Server/Speech/Components/ListenWireAction.cs @@ -1,11 +1,11 @@ using Content.Server.Chat.Systems; -using Content.Shared.Radio; -using Content.Server.Radio.Components; +using Content.Shared.Radio.Components; using Content.Server.Radio.EntitySystems; using Content.Server.Speech.Components; using Content.Server.Wires; -using Content.Shared.Wires; +using Content.Shared.Radio; using Content.Shared.Speech; +using Content.Shared.Wires; using Robust.Shared.Prototypes; namespace Content.Server.Speech; diff --git a/Content.Server/Vocalization/Systems/RadioVocalizationSystem.cs b/Content.Server/Vocalization/Systems/RadioVocalizationSystem.cs index bdb14168bb..00f6b7bbd1 100644 --- a/Content.Server/Vocalization/Systems/RadioVocalizationSystem.cs +++ b/Content.Server/Vocalization/Systems/RadioVocalizationSystem.cs @@ -1,9 +1,9 @@ using Content.Server.Chat.Systems; -using Content.Server.Radio.Components; using Content.Server.Vocalization.Components; using Content.Shared.Chat; using Content.Shared.Inventory; using Content.Shared.Radio; +using Content.Shared.Radio.Components; using Robust.Shared.Prototypes; using Robust.Shared.Random; @@ -42,9 +42,9 @@ public sealed partial class RadioVocalizationSystem : EntitySystem /// Selects a random radio channel from all ActiveRadio entities in a given entity's inventory /// If no channels are found, this returns false and sets channel to an empty string /// - private bool TryPickRandomRadioChannel(EntityUid entity, out string channel) + private bool TryPickRandomRadioChannel(EntityUid entity, out ProtoId channel) { - HashSet potentialChannels = []; + HashSet> potentialChannels = []; // we don't have to check if this entity has an inventory. GetHandOrInventoryEntities will not yield anything // if an entity has no inventory or inventory slots diff --git a/Content.Server/Radio/Components/ActiveRadioComponent.cs b/Content.Shared/Radio/Components/ActiveRadioComponent.cs similarity index 57% rename from Content.Server/Radio/Components/ActiveRadioComponent.cs rename to Content.Shared/Radio/Components/ActiveRadioComponent.cs index b0a2adbf91..25199b54e6 100644 --- a/Content.Server/Radio/Components/ActiveRadioComponent.cs +++ b/Content.Shared/Radio/Components/ActiveRadioComponent.cs @@ -1,30 +1,30 @@ -using Content.Shared.Radio; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; -namespace Content.Server.Radio.Components; +namespace Content.Shared.Radio.Components; /// /// This component is required to receive radio message events. /// -[RegisterComponent] +[RegisterComponent, NetworkedComponent] public sealed partial class ActiveRadioComponent : Component { /// /// The channels that this radio is listening on. /// - [DataField("channels", customTypeSerializer: typeof(PrototypeIdHashSetSerializer))] - public HashSet Channels = new(); + [DataField] + public HashSet> Channels = new(); /// /// A toggle for globally receiving all radio channels. /// Overrides /// - [DataField, ViewVariables(VVAccess.ReadWrite)] + [DataField] public bool ReceiveAllChannels; /// /// If this radio can hear all messages on all maps /// - [DataField("globalReceive")] + [DataField] public bool GlobalReceive = false; } diff --git a/Content.Shared/Radio/Components/EncryptionKeyComponent.cs b/Content.Shared/Radio/Components/EncryptionKeyComponent.cs index b7558d9825..54b77b5092 100644 --- a/Content.Shared/Radio/Components/EncryptionKeyComponent.cs +++ b/Content.Shared/Radio/Components/EncryptionKeyComponent.cs @@ -1,6 +1,6 @@ using Content.Shared.Chat; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; namespace Content.Shared.Radio.Components; @@ -8,15 +8,15 @@ namespace Content.Shared.Radio.Components; /// This component is currently used for providing access to channels for "HeadsetComponent"s. /// It should be used for intercoms and other radios in future. /// -[RegisterComponent] +[RegisterComponent, NetworkedComponent] public sealed partial class EncryptionKeyComponent : Component { - [DataField("channels", customTypeSerializer: typeof(PrototypeIdHashSetSerializer))] - public HashSet Channels = new(); + [DataField] + public HashSet> Channels = new(); /// /// This is the channel that will be used when using the default/department prefix (). /// - [DataField("defaultChannel", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string? DefaultChannel; + [DataField] + public ProtoId? DefaultChannel; } diff --git a/Content.Shared/Radio/Components/EncryptionKeyHolderComponent.cs b/Content.Shared/Radio/Components/EncryptionKeyHolderComponent.cs index bd49acf909..5067fe8c0c 100644 --- a/Content.Shared/Radio/Components/EncryptionKeyHolderComponent.cs +++ b/Content.Shared/Radio/Components/EncryptionKeyHolderComponent.cs @@ -2,40 +2,36 @@ using Content.Shared.Chat; using Content.Shared.Tools; using Robust.Shared.Audio; using Robust.Shared.Containers; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; namespace Content.Shared.Radio.Components; /// /// This component is by entities that can contain encryption keys /// -[RegisterComponent] +[RegisterComponent, NetworkedComponent] public sealed partial class EncryptionKeyHolderComponent : Component { /// /// Whether or not encryption keys can be removed from the headset. /// - [ViewVariables(VVAccess.ReadWrite)] - [DataField("keysUnlocked")] + [DataField] public bool KeysUnlocked = true; /// /// The tool required to extract the encryption keys from the headset. /// - [ViewVariables(VVAccess.ReadWrite)] - [DataField("keysExtractionMethod", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string KeysExtractionMethod = "Screwing"; + [DataField] + public ProtoId KeysExtractionMethod = "Screwing"; - [ViewVariables(VVAccess.ReadWrite)] - [DataField("keySlots")] + [DataField] public int KeySlots = 2; - [ViewVariables(VVAccess.ReadWrite)] - [DataField("keyExtractionSound")] + [DataField] public SoundSpecifier KeyExtractionSound = new SoundPathSpecifier("/Audio/Items/pistol_magout.ogg"); - [ViewVariables(VVAccess.ReadWrite)] - [DataField("keyInsertionSound")] + [DataField] public SoundSpecifier KeyInsertionSound = new SoundPathSpecifier("/Audio/Items/pistol_magin.ogg"); [ViewVariables] @@ -46,7 +42,7 @@ public sealed partial class EncryptionKeyHolderComponent : Component /// Combined set of radio channels provided by all contained keys. /// [ViewVariables] - public HashSet Channels = new(); + public HashSet> Channels = new(); /// /// This is the channel that will be used when using the default/department prefix (). diff --git a/Content.Server/Radio/Components/IntrinsicRadioReceiverComponent.cs b/Content.Shared/Radio/Components/IntrinsicRadioReceiverComponent.cs similarity index 73% rename from Content.Server/Radio/Components/IntrinsicRadioReceiverComponent.cs rename to Content.Shared/Radio/Components/IntrinsicRadioReceiverComponent.cs index 416dfe39cb..58d390f76d 100644 --- a/Content.Server/Radio/Components/IntrinsicRadioReceiverComponent.cs +++ b/Content.Shared/Radio/Components/IntrinsicRadioReceiverComponent.cs @@ -1,11 +1,11 @@ -namespace Content.Server.Radio.Components; +using Robust.Shared.GameStates; + +namespace Content.Shared.Radio.Components; /// /// This component allows an entity to directly translate radio messages into chat messages. Note that this does not /// automatically add an , which is required to receive radio messages on specific /// channels. /// -[RegisterComponent] -public sealed partial class IntrinsicRadioReceiverComponent : Component -{ -} +[RegisterComponent, NetworkedComponent] +public sealed partial class IntrinsicRadioReceiverComponent : Component; diff --git a/Content.Shared/Radio/Components/IntrinsicRadioTransmitterComponent.cs b/Content.Shared/Radio/Components/IntrinsicRadioTransmitterComponent.cs new file mode 100644 index 0000000000..c9dca99a2e --- /dev/null +++ b/Content.Shared/Radio/Components/IntrinsicRadioTransmitterComponent.cs @@ -0,0 +1,16 @@ +using Content.Shared.Chat; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Radio.Components; + +/// +/// This component allows an entity to directly translate spoken text into radio messages (effectively an intrinsic +/// radio headset). +/// +[RegisterComponent, NetworkedComponent] +public sealed partial class IntrinsicRadioTransmitterComponent : Component +{ + [DataField] + public HashSet> Channels = new() { SharedChatSystem.CommonChannel }; +} diff --git a/Content.Shared/Radio/Components/RadioMicrophoneComponent.cs b/Content.Shared/Radio/Components/RadioMicrophoneComponent.cs new file mode 100644 index 0000000000..25f4100212 --- /dev/null +++ b/Content.Shared/Radio/Components/RadioMicrophoneComponent.cs @@ -0,0 +1,40 @@ +using Content.Shared.Radio.EntitySystems; +using Content.Shared.Chat; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Radio.Components; + +/// +/// Listens for local chat messages and relays them to some radio frequency +/// +[RegisterComponent, NetworkedComponent] +[Access(typeof(SharedRadioDeviceSystem))] +public sealed partial class RadioMicrophoneComponent : Component +{ + [DataField] + public ProtoId BroadcastChannel = SharedChatSystem.CommonChannel; + + [DataField] + public int ListenRange = 4; + + [DataField] + public bool Enabled = false; + + [DataField] + public bool PowerRequired = false; + + /// + /// Whether or not interacting with this entity + /// toggles it on or off. + /// + [DataField] + public bool ToggleOnInteract = true; + + /// + /// Whether or not the speaker must have an + /// unobstructed path to the radio to speak + /// + [DataField] + public bool UnobstructedRequired = false; +} diff --git a/Content.Shared/Radio/Components/RadioSpeakerComponent.cs b/Content.Shared/Radio/Components/RadioSpeakerComponent.cs new file mode 100644 index 0000000000..b7dff28def --- /dev/null +++ b/Content.Shared/Radio/Components/RadioSpeakerComponent.cs @@ -0,0 +1,27 @@ +using Content.Shared.Radio.EntitySystems; +using Content.Shared.Chat; +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Radio.Components; + +/// +/// Listens for radio messages and relays them to local chat. +/// +[RegisterComponent, NetworkedComponent, AutoGenerateComponentState] +[Access(typeof(SharedRadioDeviceSystem))] +public sealed partial class RadioSpeakerComponent : Component +{ + /// + /// Whether or not interacting with this entity + /// toggles it on or off. + /// + [DataField] + public bool ToggleOnInteract = true; + + [DataField] + public HashSet> Channels = new() { SharedChatSystem.CommonChannel }; + + [DataField, AutoNetworkedField] + public bool Enabled; +} diff --git a/Content.Server/Radio/Components/WearingHeadsetComponent.cs b/Content.Shared/Radio/Components/WearingHeadsetComponent.cs similarity index 62% rename from Content.Server/Radio/Components/WearingHeadsetComponent.cs rename to Content.Shared/Radio/Components/WearingHeadsetComponent.cs index 2d68b44a3c..974044261b 100644 --- a/Content.Server/Radio/Components/WearingHeadsetComponent.cs +++ b/Content.Shared/Radio/Components/WearingHeadsetComponent.cs @@ -1,13 +1,13 @@ -using Content.Server.Radio.EntitySystems; +using Robust.Shared.GameStates; -namespace Content.Server.Radio.Components; +namespace Content.Shared.Radio.Components; /// /// This component is used to tag players that are currently wearing an ACTIVE headset. /// -[RegisterComponent] +[RegisterComponent, NetworkedComponent] public sealed partial class WearingHeadsetComponent : Component { - [DataField("headset")] + [DataField] public EntityUid Headset; } diff --git a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs index b7ceba6ee9..0b12bbc53f 100644 --- a/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs +++ b/Content.Shared/Radio/EntitySystems/EncryptionKeySystem.cs @@ -207,7 +207,7 @@ public sealed partial class EncryptionKeySystem : EntitySystem /// HashSet of channels in headset, encryptionkey or etc. /// IPrototypeManager for getting prototypes of channels with their variables. /// String that provide id of pattern in .ftl files to format channel with variables of it. - public void AddChannelsExamine(HashSet channels, string? defaultChannel, ExaminedEvent examineEvent, IPrototypeManager protoManager, string channelFTLPattern) + public void AddChannelsExamine(HashSet> channels, string? defaultChannel, ExaminedEvent examineEvent, IPrototypeManager protoManager, string channelFTLPattern) { RadioChannelPrototype? proto; foreach (var id in channels) diff --git a/Content.Shared/Radio/EntitySystems/SharedRadioDeviceSystem.cs b/Content.Shared/Radio/EntitySystems/SharedRadioDeviceSystem.cs new file mode 100644 index 0000000000..715310f55d --- /dev/null +++ b/Content.Shared/Radio/EntitySystems/SharedRadioDeviceSystem.cs @@ -0,0 +1,53 @@ +using Content.Shared.Popups; +using Content.Shared.Radio.Components; + +namespace Content.Shared.Radio.EntitySystems; + +public abstract class SharedRadioDeviceSystem : EntitySystem +{ + [Dependency] private readonly SharedPopupSystem _popup = default!; + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; + + #region Toggling + public void ToggleRadioMicrophone(EntityUid uid, EntityUid user, bool quiet = false, RadioMicrophoneComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + SetMicrophoneEnabled(uid, user, !component.Enabled, quiet, component); + } + + public virtual void SetMicrophoneEnabled(EntityUid uid, EntityUid? user, bool enabled, bool quiet = false, RadioMicrophoneComponent? component = null) { } + + public void ToggleRadioSpeaker(EntityUid uid, EntityUid user, bool quiet = false, RadioSpeakerComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + SetSpeakerEnabled(uid, user, !component.Enabled, quiet, component); + } + + public void SetSpeakerEnabled(EntityUid uid, EntityUid? user, bool enabled, bool quiet = false, RadioSpeakerComponent? component = null) + { + if (!Resolve(uid, ref component)) + return; + + component.Enabled = enabled; + Dirty(uid, component); + + if (!quiet && user != null) + { + var state = Loc.GetString(component.Enabled ? "handheld-radio-component-on-state" : "handheld-radio-component-off-state"); + var message = Loc.GetString("handheld-radio-component-on-use", ("radioState", state)); + _popup.PopupEntity(message, user.Value, user.Value); + } + + _appearance.SetData(uid, RadioDeviceVisuals.Speaker, component.Enabled); + if (component.Enabled) + EnsureComp(uid).Channels.UnionWith(component.Channels); + else + RemCompDeferred(uid); + } + #endregion +} + diff --git a/Content.Shared/Silicons/Laws/Components/SiliconLawBoundComponent.cs b/Content.Shared/Silicons/Laws/Components/SiliconLawBoundComponent.cs index 0fb9c5920f..834d2eb778 100644 --- a/Content.Shared/Silicons/Laws/Components/SiliconLawBoundComponent.cs +++ b/Content.Shared/Silicons/Laws/Components/SiliconLawBoundComponent.cs @@ -1,4 +1,5 @@ using Content.Shared.Actions; +using Content.Shared.Radio; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; using Robust.Shared.Serialization; @@ -51,9 +52,9 @@ public enum SiliconLawsUiKey : byte public sealed class SiliconLawBuiState : BoundUserInterfaceState { public List Laws; - public HashSet? RadioChannels; + public HashSet>? RadioChannels; - public SiliconLawBuiState(List laws, HashSet? radioChannels) + public SiliconLawBuiState(List laws, HashSet>? radioChannels) { Laws = laws; RadioChannels = radioChannels;