CatStation/Content.Server/TurretController/DeployableTurretControllerSystem.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

150 lines
5.5 KiB
C#

using Content.Server.DeviceNetwork.Systems;
using Content.Shared.Access;
using Content.Shared.DeviceNetwork.Components;
using Content.Shared.DeviceNetwork.Events;
using Content.Shared.DeviceNetwork.Systems;
using Content.Shared.TurretController;
using Content.Shared.Turrets;
using Robust.Server.GameObjects;
using Robust.Shared.Prototypes;
using System.Linq;
using Content.Server.Administration.Logs;
using Content.Shared.Database;
namespace Content.Server.TurretController;
/// <inheritdoc/>
public sealed partial class DeployableTurretControllerSystem : SharedDeployableTurretControllerSystem
{
[Dependency] private UserInterfaceSystem _userInterfaceSystem = default!;
[Dependency] private DeviceNetworkSystem _deviceNetwork = default!;
[Dependency] private DeviceListSystem _deviceList = default!;
[Dependency] private IAdminLogManager _adminLogger = default!;
[SubscribeLocalEvent]
private void OnBUIOpened(Entity<DeployableTurretControllerComponent> ent, ref BoundUIOpenedEvent args)
{
if (!TryComp<DeviceNetworkComponent>(ent, out var deviceNetwork))
return;
var payload = new TurretControllerRequestPayload();
foreach (var (address, _) in _deviceList.GetDeviceList(ent.Owner))
{
_deviceNetwork.SendPacket((ent.Owner, deviceNetwork), address, ref payload);
}
UpdateUIState(ent);
}
[SubscribeLocalEvent]
private void OnDeviceListUpdate(Entity<DeployableTurretControllerComponent> ent, ref DeviceListUpdateEvent args)
{
if (!TryComp<DeviceNetworkComponent>(ent, out var deviceNetwork))
return;
// List of new added turrets
var turretsToAdd = args.Devices.Except(args.OldDevices);
// Request data from newly linked devices
var payload = new TurretControllerRequestPayload();
foreach (var turretUid in turretsToAdd)
{
if (!HasComp<DeployableTurretComponent>(turretUid))
continue;
if (!TryComp<DeviceNetworkComponent>(turretUid, out var turretDeviceNetwork))
continue;
_deviceNetwork.SendPacket((ent.Owner, deviceNetwork), turretDeviceNetwork.Address, ref payload);
}
// Remove newly unlinked devices
var turretsToRemove = args.OldDevices.Except(args.Devices);
var refreshUi = false;
foreach (var turretUid in turretsToRemove)
{
if (!TryComp<DeviceNetworkComponent>(turretUid, out var turretDeviceNetwork))
continue;
if (ent.Comp.LinkedTurrets.Remove(turretDeviceNetwork.Address))
refreshUi = true;
}
if (refreshUi)
UpdateUIState(ent);
}
[SubscribeLocalEvent]
private void OnPacketReceived(Entity<DeployableTurretControllerComponent> ent, ref DeviceNetworkPacketEvent<TurretStatePayload> args)
{
if (!TryComp<DeviceNetworkComponent>(ent, out var deviceNetwork) || deviceNetwork.ReceiveFrequency != args.Frequency)
return;
// If an update was received from a turret, connect to it and update the UI
ent.Comp.LinkedTurrets[args.SenderAddress] = args.Data.State;
UpdateUIState(ent);
}
protected override void ChangeArmamentSetting(Entity<DeployableTurretControllerComponent> ent, int armamentState, EntityUid? user = null)
{
base.ChangeArmamentSetting(ent, armamentState, user);
if (!TryComp<DeviceNetworkComponent>(ent, out var device))
return;
// Update linked turrets' armament statuses
var payload = new TurretControllerSetArmamentPayload
{
ArmamentState = armamentState,
};
_adminLogger.Add(LogType.ItemConfigure, LogImpact.Medium, $"{ToPrettyString(user)} set {ToPrettyString(ent)} to {armamentState}");
_deviceNetwork.SendPacket((ent.Owner, device), null, ref payload);
}
protected override void ChangeExemptAccessLevels(
Entity<DeployableTurretControllerComponent> ent,
HashSet<ProtoId<AccessLevelPrototype>> exemptions,
bool enabled,
EntityUid? user = null
)
{
base.ChangeExemptAccessLevels(ent, exemptions, enabled, user);
if (!TryComp<DeviceNetworkComponent>(ent, out var device) ||
!TryComp<TurretTargetSettingsComponent>(ent, out var turretTargetingSettings))
return;
// Update linked turrets' target selection exemptions
var payload = new TurretControllerSetAccessPayload
{
AccessExemptions = turretTargetingSettings.ExemptAccessLevels,
};
foreach (var exemption in exemptions)
{
_adminLogger.Add(LogType.ItemConfigure, LogImpact.Medium, $"{ToPrettyString(user)} set {ToPrettyString(ent)} authorization of {exemption} to {enabled}");
}
_deviceNetwork.SendPacket((ent.Owner, device), null, ref payload);
}
private void UpdateUIState(Entity<DeployableTurretControllerComponent> ent)
{
var turretStates = new Dictionary<string, string>();
foreach (var (address, state) in ent.Comp.LinkedTurrets)
{
var stateName = state.ToString().ToLower();
var stateDesc = Loc.GetString("turret-controls-window-turret-" + stateName);
turretStates.Add(address, stateDesc);
}
var uiState = new DeployableTurretControllerBoundInterfaceState(turretStates);
_userInterfaceSystem.SetUiState(ent.Owner, DeployableTurretControllerUiKey.Key, uiState);
}
}