using Content.Shared.Chat; using Content.Shared.Inventory.Events; using Content.Shared.Radio; using Content.Shared.Radio.Components; using Content.Shared.Radio.EntitySystems; using Robust.Shared.Network; using Robust.Shared.Player; namespace Content.Server.Radio.EntitySystems; public sealed class HeadsetSystem : SharedHeadsetSystem { [Dependency] private readonly INetManager _netMan = default!; [Dependency] private readonly RadioSystem _radio = default!; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnHeadsetReceive); SubscribeLocalEvent(OnKeysChanged); SubscribeLocalEvent(OnSpeak); } private void OnKeysChanged(EntityUid uid, HeadsetComponent component, EncryptionChannelsChangedEvent args) { UpdateRadioChannels(uid, component, args.Component); } private void UpdateRadioChannels(EntityUid uid, HeadsetComponent headset, EncryptionKeyHolderComponent? keyHolder = null) { // make sure to not add ActiveRadioComponent when headset is being deleted if (!headset.Enabled || MetaData(uid).EntityLifeStage >= EntityLifeStage.Terminating) return; if (!Resolve(uid, ref keyHolder)) return; if (keyHolder.Channels.Count == 0) RemComp(uid); else EnsureComp(uid).Channels = new(keyHolder.Channels); } private void OnSpeak(EntityUid uid, WearingHeadsetComponent component, EntitySpokeEvent args) { if (args.Channel != null && TryComp(component.Headset, out EncryptionKeyHolderComponent? keys) && keys.Channels.Contains(args.Channel.ID)) { _radio.SendRadioMessage(uid, args.Message, args.Channel, component.Headset); args.Channel = null; // prevent duplicate messages from other listeners. } } protected override void OnGotEquipped(EntityUid uid, HeadsetComponent component, GotEquippedEvent args) { base.OnGotEquipped(uid, component, args); if (component.IsEquipped && component.Enabled) { EnsureComp(args.Equipee).Headset = uid; UpdateRadioChannels(uid, component); } } protected override void OnGotUnequipped(EntityUid uid, HeadsetComponent component, GotUnequippedEvent args) { base.OnGotUnequipped(uid, component, args); RemComp(uid); RemComp(args.Equipee); } public void SetEnabled(EntityUid uid, bool value, HeadsetComponent? component = null) { if (!Resolve(uid, ref component)) return; if (component.Enabled == value) return; component.Enabled = value; Dirty(uid, component); if (!value) { RemCompDeferred(uid); if (component.IsEquipped) RemCompDeferred(Transform(uid).ParentUid); } else if (component.IsEquipped) { EnsureComp(Transform(uid).ParentUid).Headset = uid; UpdateRadioChannels(uid, component); } } private void OnHeadsetReceive(EntityUid uid, HeadsetComponent component, ref RadioReceiveEvent args) { // TODO: change this when a code refactor is done // this is currently done this way because receiving radio messages on an entity otherwise requires that entity // to have an ActiveRadioComponent var parent = Transform(uid).ParentUid; if (parent.IsValid()) { var relayEvent = new HeadsetRadioReceiveRelayEvent(args); RaiseLocalEvent(parent, ref relayEvent); } if (TryComp(parent, out ActorComponent? actor)) _netMan.ServerSendMessage(args.ChatMsg, actor.PlayerSession.Channel); } }