using Content.Server.Chat.Systems; using Content.Server.Radio; using Content.Server.Radio.Components; using Content.Server.Radio.EntitySystems; using Content.Shared.DeltaV.Implants.Radio; using Content.Shared.Radio.Components; using Robust.Shared.Containers; using Robust.Shared.Network; using Robust.Shared.Player; namespace Content.Server.DeltaV.Implants.Radio; /// public sealed class RadioImplantSystem : SharedRadioImplantSystem { [Dependency] private readonly INetManager _netManager = default!; [Dependency] private readonly RadioSystem _radioSystem = default!; private EntityQuery _actorQuery; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent(OnInsertEncryptionKey); SubscribeLocalEvent(OnRemoveEncryptionKey); SubscribeLocalEvent(OnRadioReceive); SubscribeLocalEvent(OnSpeak); _actorQuery = GetEntityQuery(); } /// /// Ensures implants with fixed channels work. /// private void OnMapInit(Entity ent, ref MapInitEvent args) { UpdateRadioReception(ent); } /// /// Handles the implantee's speech being forwarded onto the radio channel of the implant. /// private void OnSpeak(Entity ent, ref EntitySpokeEvent args) { // not a radio message, or already handled by another radio if (args.Channel is null) return; // does the implant have access to the channel the implantee is trying to speak on? if (ent.Comp.Implant is {} implant && TryComp(implant, out var radioImplantComponent) && radioImplantComponent.Channels.Contains(args.Channel.ID)) { _radioSystem.SendRadioMessage(ent, args.Message, args.Channel.ID, implant); // prevent other radios they might be wearing from sending the message again args.Channel = null; } } /// /// Handles receiving radio messages and forwarding them to the implantee. /// private void OnRadioReceive(EntityUid uid, RadioImplantComponent component, ref RadioReceiveEvent args) { if (_actorQuery.TryComp(component.Implantee, out var actorComponent)) _netManager.ServerSendMessage(args.ChatMsg, actorComponent.PlayerSession.Channel); } /// /// Handles the addition of an encryption key to the implant's storage. /// private void OnInsertEncryptionKey(Entity ent, ref EntInsertedIntoContainerMessage args) { // check if the insertion is actually something getting inserted into the radio implant storage, since // this evt also fires when the radio implant is being inserted into a person. if (ent.Owner != args.Container.Owner || !TryComp(args.Entity, out var encryptionKeyComponent)) return; // copy over the radio channels that can be accessed ent.Comp.Channels.Clear(); foreach (var channel in encryptionKeyComponent.Channels) { ent.Comp.Channels.Add(channel); } Dirty(ent); UpdateRadioReception(ent); } /// /// Handles the removal of an encryption key from the implant's storage. /// private void OnRemoveEncryptionKey(Entity ent, ref EntRemovedFromContainerMessage args) { // check if the insertion is actually something getting inserted into the radio implant storage, since // this evt also fires when the radio implant is being inserted into a person. if (ent.Owner != args.Container.Owner || !HasComp(args.Entity)) return; // clear the radio channels since there's no encryption key inserted anymore. ent.Comp.Channels.Clear(); Dirty(ent); UpdateRadioReception(ent); } /// /// Ensures that this thing can actually hear radio messages from channels the key provides. /// private void UpdateRadioReception(Entity ent) { if (ent.Comp.Channels.Count != 0) { // we need to add this comp to actually receive radio events. var channels = EnsureComp(ent).Channels; foreach (var channel in ent.Comp.Channels) { channels.Add(channel); } } else { RemComp(ent); } } }