--- /dev/null
+using Content.Server.DeviceNetwork.Components;
+using Content.Shared.DeviceNetwork.Components;
+using Robust.Server.GameObjects;
+
+namespace Content.Server.DeviceNetwork.Systems;
+
+public sealed class DeviceNetworkJammerSystem : EntitySystem
+{
+ [Dependency] private TransformSystem _transform = default!;
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent<TransformComponent, BeforePacketSentEvent>(BeforePacketSent);
+ }
+
+ private void BeforePacketSent(EntityUid uid, TransformComponent xform, BeforePacketSentEvent ev)
+ {
+ if (ev.Cancelled)
+ return;
+
+ var query = EntityQueryEnumerator<DeviceNetworkJammerComponent, TransformComponent>();
+
+ while (query.MoveNext(out _, out var jammerComp, out var jammerXform))
+ {
+ if (!jammerComp.JammableNetworks.Contains(ev.NetworkId))
+ continue;
+
+ if (jammerXform.Coordinates.InRange(EntityManager, _transform, ev.SenderTransform.Coordinates, jammerComp.Range)
+ || jammerXform.Coordinates.InRange(EntityManager, _transform, xform.Coordinates, jammerComp.Range))
+ {
+ ev.Cancel();
+ return;
+ }
+ }
+ }
+
+}
var xform = Transform(packet.Sender);
- BeforePacketSentEvent beforeEv = new(packet.Sender, xform, _transformSystem.GetWorldPosition(xform));
+ var senderPos = _transformSystem.GetWorldPosition(xform);
foreach (var connection in connections)
{
if (connection.Owner == packet.Sender)
continue;
+ BeforePacketSentEvent beforeEv = new(packet.Sender, xform, senderPos, connection.NetIdEnum.ToString());
RaiseLocalEvent(connection.Owner, beforeEv, false);
if (!beforeEv.Cancelled)
/// </summary>
public readonly Vector2 SenderPosition;
- public BeforePacketSentEvent(EntityUid sender, TransformComponent xform, Vector2 senderPosition)
+ /// <summary>
+ /// The network the packet will be sent to.
+ /// </summary>
+ public readonly string NetworkId;
+
+ public BeforePacketSentEvent(EntityUid sender, TransformComponent xform, Vector2 senderPosition, string networkId)
{
Sender = sender;
SenderTransform = xform;
SenderPosition = senderPosition;
+ NetworkId = networkId;
}
}
-using Content.Server.DeviceNetwork.Components;
+using System.Diagnostics.CodeAnalysis;
+using Content.Server.DeviceNetwork.Components;
using Content.Server.Medical.CrewMonitoring;
using Content.Server.Power.Components;
using Content.Server.Station.Systems;
/// <param name="address">The address of the active server if it exists</param>
/// <typeparam name="TComp">The component type that determines what type of server you're getting the address of</typeparam>
/// <returns>True if there is an active serve. False otherwise</returns>
- public bool TryGetActiveServerAddress<TComp>(EntityUid stationId, out string? address) where TComp : IComponent
+ public bool TryGetActiveServerAddress<TComp>(EntityUid stationId, [NotNullWhen(true)] out string? address) where TComp : IComponent
{
var servers = EntityQueryEnumerator<
SingletonDeviceNetServerComponent,
[DataField, ViewVariables]
public bool PreviousControlsLocked = false;
}
-
-[ByRefEvent]
-public record struct SuitSensorsSendAttemptEvent
-{
- public bool Cancelled;
-};
// TODO: This would cause imprecision at different tick rates.
sensor.NextUpdate = curTime + sensor.UpdateRate;
- var canEv = new SuitSensorsSendAttemptEvent();
- RaiseLocalEvent(uid, ref canEv);
- if (canEv.Cancelled)
- continue;
-
// get sensor status
var status = GetSensorState(uid, sensor);
if (status == null)
-using Content.Server.Medical.SuitSensors;
+using Content.Server.DeviceNetwork.Components;
+using Content.Server.DeviceNetwork.Systems;
+using Content.Server.Medical.CrewMonitoring;
using Content.Server.Popups;
using Content.Server.Power.EntitySystems;
using Content.Server.PowerCell;
using Content.Server.Radio.Components;
+using Content.Server.Station.Systems;
+using Content.Shared.DeviceNetwork.Components;
using Content.Shared.Examine;
using Content.Shared.Interaction;
using Content.Shared.PowerCell.Components;
[Dependency] private readonly BatterySystem _battery = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
+ [Dependency] private readonly StationSystem _stationSystem = default!;
+ [Dependency] private readonly SingletonDeviceNetServerSystem _singletonServerSystem = default!;
public override void Initialize()
{
SubscribeLocalEvent<ActiveRadioJammerComponent, PowerCellChangedEvent>(OnPowerCellChanged);
SubscribeLocalEvent<RadioJammerComponent, ExaminedEvent>(OnExamine);
SubscribeLocalEvent<RadioSendAttemptEvent>(OnRadioSendAttempt);
- SubscribeLocalEvent<SuitSensorComponent, SuitSensorsSendAttemptEvent>(OnSensorSendAttempt);
}
public override void Update(float frameTime)
!_battery.TryUseCharge(batteryUid.Value, jam.Wattage * frameTime, battery))
{
RemComp<ActiveRadioJammerComponent>(uid);
+ RemComp<DeviceNetworkJammerComponent>(uid);
}
}
}
if (activated)
{
EnsureComp<ActiveRadioJammerComponent>(uid);
+ var stationId = _stationSystem.GetOwningStation(uid);
+ if (stationId != null && _singletonServerSystem.TryGetActiveServerAddress<CrewMonitoringServerComponent>(stationId.Value, out var netId))
+ {
+ EnsureComp<DeviceNetworkJammerComponent>(uid, out var jammingComp);
+ jammingComp.Range = comp.Range;
+ jammingComp.JammableNetworks.Add(netId);
+ Dirty(uid, jammingComp);
+ }
}
else
{
RemComp<ActiveRadioJammerComponent>(uid);
+ RemComp<DeviceNetworkJammerComponent>(uid);
}
var state = Loc.GetString(activated ? "radio-jammer-component-on-state" : "radio-jammer-component-off-state");
var message = Loc.GetString("radio-jammer-component-on-use", ("state", state));
}
}
- private void OnSensorSendAttempt(EntityUid uid, SuitSensorComponent comp, ref SuitSensorsSendAttemptEvent args)
- {
- if (ShouldCancelSend(uid))
- {
- args.Cancelled = true;
- }
- }
-
private bool ShouldCancelSend(EntityUid sourceUid)
{
var source = Transform(sourceUid).Coordinates;
--- /dev/null
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.DeviceNetwork.Components;
+
+/// <summary>
+/// Allow entities to jam DeviceNetwork packets.
+/// </summary>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class DeviceNetworkJammerComponent : Component
+{
+ /// <summary>
+ /// Range where packets will be jammed. This is checked both against the sender and receiver.
+ /// </summary>
+ [DataField, AutoNetworkedField]
+ public float Range = 5.0f;
+
+ /// <summary>
+ /// Device networks that can be jammed. For a list of default NetworkIds see DeviceNetIdDefaults on Content.Server.
+ /// Network ids are not guaranteed to be limited to DeviceNetIdDefaults.
+ /// </summary>
+ [DataField, AutoNetworkedField]
+ public HashSet<string> JammableNetworks = [];
+
+}