CatStation/Content.Server/SurveillanceCamera/Systems/SurveillanceCameraMapSystem.cs
Rouden cc2c14f8e4
Device Network refactor part 1: API improvements (#44346)
* Refactor DeviceNetwork

* Singleton

* NetworkPayloads refactor

* Reorganize DeviceNetworkSystem

* Surveillance cameras

* Fix code

* Fix build

* Fix test fail by rewriting entire singleton logic

* Properly predict examine

* Update DeviceNetworkSystem.API.cs

* Update EntityTest.cs

* Update DeviceNetworkSystem.cs

* Alright I'll do this expensive check fine

* Fix disposals debug assert

* Implement device network static events support

* Use frozen dictionaries for performance

* Update SharedDeviceNetworkSystem.Payloads.cs

* Parallel payload handling support

* Fix some spagetti-code

* Optimize NetworkPayload cancellation

* Parallel payloads are now cancellable

* Fix screens

* Fix robotics console

* Allow new methods for shared

* Mail fix

* Turret fix

* Fix network system method usage + signal and borg fix

* finally fix atmos devices OH MY GOOOD

* Remove stupid parallelism from fax

* Fix surveiollance cameras

* Working on a single thing for 2 days straight award

* Fix the test?

* Update units.yml

* Add IDevice interface because why not

* Add more device network suffixes

* Fix camera router failing test

* yaml linter peak

* Improve docs for DeviceNetworkHandlers

* fix build

* Update CartridgeLoaderSystem.Relay.cs

* Remove parallel system and EntitySystem post init

* Add more docs and also events

* Remove unnecessary caching

* Update DevicePayloadComponentSystem.cs

* Back to entity events

* Implement DeviceData

* Remove serializable from payloads

* Update DeviceData.cs

* Add a prototype for a singleton

* Fix tests

* Fix air alarms

* Update DeviceNetworkSystem.cs

* Fix cameras

* Make camera router event-less

* Fix atmos sync payloads, add more docs

* Remove singleton + instant packets

* oops remove public access

* Fix tests?

* Why the hell overload effect makes puddle sparks

* Apparently it was redundant

* Update gates.yml

* Finish documentation

* Review

* Mark relay properties as obsolete

* Struct payloads support (#blazinglyfastmemorysafe)

* Update DeviceNetworkTest.cs

* Make device structs stuff better

* Move address prefix to DeviceNetworkComponent

* Locale fixes

* Fix tests

* Doesn't know boolean logic award

* Update AtmosAlarmableSystem.cs

* Fix address predicted examine

* Partial fix to air alarmables

* Fix deployable turrets UI

* Fix firelocks, maybe

* Apparently Activatable UI was enough lol

* Fix surveillance cameras

* Rename `QueuePacket` into `SendPacket`

* Simplify DeviceData as much as possible

* Update DeviceData.cs

* Update FaxMachineComponent.cs

* Remove DeviceData because its stupid

* Update ScreenSystem.cs

* Fix build (camera map broken still)

* Fix map

* fix usings

* Review changes

* Build fix
2026-08-31 19:42:56 +00:00

154 lines
5.1 KiB
C#

using System.Numerics;
using Content.Server.DeviceNetwork.Systems;
using Content.Server.Power.Components;
using Content.Shared.DeviceNetwork.Components;
using Content.Shared.SurveillanceCamera.Components;
namespace Content.Server.SurveillanceCamera;
public sealed partial class SurveillanceCameraMapSystem : EntitySystem
{
[Dependency] private SharedTransformSystem _transform = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<SurveillanceCameraComponent, MapInitEvent>(OnCameraInit, after: [typeof(DeviceNetworkSystem)]);
SubscribeLocalEvent<SurveillanceCameraComponent, MoveEvent>(OnCameraMoved);
SubscribeNetworkEvent<RequestCameraMarkerUpdateMessage>(OnRequestCameraMarkerUpdate);
}
private void OnCameraInit(Entity<SurveillanceCameraComponent> ent, ref MapInitEvent args)
{
UpdateCameraMarker(ent);
}
private void OnCameraMoved(Entity<SurveillanceCameraComponent> ent, ref MoveEvent args)
{
if (!args.ParentChanged)
{
UpdateCameraMarker(ent);
return;
}
var oldGridUid = _transform.GetGrid(args.OldPosition);
var newGridUid = args.Component.GridUid;
if (oldGridUid != newGridUid && oldGridUid is not null && !TerminatingOrDeleted(oldGridUid.Value))
{
if (TryComp<SurveillanceCameraMapComponent>(oldGridUid, out var oldMapComp))
{
var netEntity = GetNetEntity(ent.Owner);
if (oldMapComp.Cameras.Remove(netEntity))
Dirty(oldGridUid.Value, oldMapComp);
}
}
if (newGridUid is not null && !TerminatingOrDeleted(newGridUid.Value))
UpdateCameraMarker(ent);
}
private void OnRequestCameraMarkerUpdate(RequestCameraMarkerUpdateMessage args)
{
var cameraEntity = GetEntity(args.CameraEntity);
if (TryComp<SurveillanceCameraComponent>(cameraEntity, out var comp)
&& HasComp<DeviceNetworkComponent>(cameraEntity))
UpdateCameraMarker((cameraEntity, comp));
}
/// <summary>
/// Updates camera data in the SurveillanceCameraMapComponent for the specified camera entity.
/// </summary>
public void UpdateCameraMarker(Entity<SurveillanceCameraComponent> camera)
{
var (uid, comp) = camera;
if (TerminatingOrDeleted(uid))
return;
if (!TryComp(uid, out TransformComponent? xform) || !TryComp(uid, out DeviceNetworkComponent? deviceNet))
return;
var gridUid = xform.GridUid;
if (gridUid is null)
return;
if (deviceNet.ReceiveFrequencyId == null)
return;
var netEntity = GetNetEntity(uid);
var mapComp = EnsureComp<SurveillanceCameraMapComponent>(gridUid.Value);
var worldPos = _transform.GetWorldPosition(xform);
var gridMatrix = _transform.GetInvWorldMatrix(Transform(gridUid.Value));
var localPos = Vector2.Transform(worldPos, gridMatrix);
var address = deviceNet.Address;
var subnet = deviceNet.ReceiveFrequencyId.Value;
var powered = CompOrNull<ApcPowerReceiverComponent>(uid)?.Powered ?? true;
var active = comp.Active && powered;
var exists = mapComp.Cameras.TryGetValue(netEntity, out var existing);
if (exists &&
existing.Position.Equals(localPos) &&
existing.Active == active &&
existing.Address == address &&
existing.Subnet == subnet)
{
return;
}
var visible = exists ? existing.Visible : true;
mapComp.Cameras[netEntity] = new CameraMarker
{
Position = localPos,
Active = active,
Address = address,
Subnet = subnet,
Visible = visible
};
Dirty(gridUid.Value, mapComp);
}
/// <summary>
/// Sets the visibility state of a camera on the camera map.
/// </summary>
public void SetCameraVisibility(EntityUid cameraUid, bool visible)
{
if (!TryComp(cameraUid, out TransformComponent? xform))
return;
var gridUid = xform.GridUid;
if (gridUid is null || !TryComp<SurveillanceCameraMapComponent>(gridUid.Value, out var mapComp))
return;
var netEntity = GetNetEntity(cameraUid);
if (mapComp.Cameras.TryGetValue(netEntity, out var marker) && marker.Visible != visible)
{
marker.Visible = visible;
mapComp.Cameras[netEntity] = marker;
Dirty(gridUid.Value, mapComp);
}
}
/// <summary>
/// Checks if a camera is currently visible on the camera map.
/// </summary>
public bool IsCameraVisible(EntityUid cameraUid)
{
if (!TryComp(cameraUid, out TransformComponent? xform))
return false;
var gridUid = xform.GridUid;
if (gridUid is null || !TryComp<SurveillanceCameraMapComponent>(gridUid, out var mapComp))
return false;
var netEntity = GetNetEntity(cameraUid);
return mapComp.Cameras.TryGetValue(netEntity, out var marker) && marker.Visible;
}
}