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);
}
}
}