using Content.Server.DeviceNetwork.Systems; using Content.Shared.Access; using Content.Shared.DeviceNetwork; 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; /// public sealed partial class DeployableTurretControllerSystem : SharedDeployableTurretControllerSystem { [Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!; [Dependency] private readonly DeviceNetworkSystem _deviceNetwork = default!; [Dependency] private readonly IAdminLogManager _adminLogger = default!; /// Keys for the device network. See for further examples. public const string CmdSetArmamemtState = "set_armament_state"; public const string CmdSetAccessExemptions = "set_access_exemption"; public override void Initialize() { base.Initialize(); SubscribeLocalEvent(OnBUIOpened); SubscribeLocalEvent(OnDeviceListUpdate); SubscribeLocalEvent(OnPacketReceived); } private void OnBUIOpened(Entity ent, ref BoundUIOpenedEvent args) { UpdateUIState(ent); } private void OnDeviceListUpdate(Entity ent, ref DeviceListUpdateEvent args) { if (!TryComp(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 NetworkPayload { [DeviceNetworkConstants.Command] = DeviceNetworkConstants.CmdUpdatedState, }; foreach (var turretUid in turretsToAdd) { if (!HasComp(turretUid)) continue; if (!TryComp(turretUid, out var turretDeviceNetwork)) continue; _deviceNetwork.QueuePacket(ent, turretDeviceNetwork.Address, payload, device: deviceNetwork); } // Remove newly unlinked devices var turretsToRemove = args.OldDevices.Except(args.Devices); var refreshUi = false; foreach (var turretUid in turretsToRemove) { if (!TryComp(turretUid, out var turretDeviceNetwork)) continue; if (ent.Comp.LinkedTurrets.Remove(turretDeviceNetwork.Address)) refreshUi = true; } if (refreshUi) UpdateUIState(ent); } private void OnPacketReceived(Entity ent, ref DeviceNetworkPacketEvent args) { if (!args.Data.TryGetValue(DeviceNetworkConstants.Command, out string? command)) return; if (!TryComp(ent, out var deviceNetwork) || deviceNetwork.ReceiveFrequency != args.Frequency) return; // If an update was received from a turret, connect to it and update the UI if (command == DeviceNetworkConstants.CmdUpdatedState && args.Data.TryGetValue(command, out DeployableTurretState updatedState)) { ent.Comp.LinkedTurrets[args.SenderAddress] = updatedState; UpdateUIState(ent); } } protected override void ChangeArmamentSetting(Entity ent, int armamentState, EntityUid? user = null) { base.ChangeArmamentSetting(ent, armamentState, user); if (!TryComp(ent, out var device)) return; // Update linked turrets' armament statuses var payload = new NetworkPayload { [DeviceNetworkConstants.Command] = CmdSetArmamemtState, [CmdSetArmamemtState] = armamentState, }; _adminLogger.Add(LogType.ItemConfigure, LogImpact.Medium, $"{ToPrettyString(user)} set {ToPrettyString(ent)} to {armamentState}"); _deviceNetwork.QueuePacket(ent, null, payload, device: device); } protected override void ChangeExemptAccessLevels( Entity ent, HashSet> exemptions, bool enabled, EntityUid? user = null ) { base.ChangeExemptAccessLevels(ent, exemptions, enabled, user); if (!TryComp(ent, out var device) || !TryComp(ent, out var turretTargetingSettings)) return; // Update linked turrets' target selection exemptions var payload = new NetworkPayload { [DeviceNetworkConstants.Command] = CmdSetAccessExemptions, [CmdSetAccessExemptions] = turretTargetingSettings.ExemptAccessLevels, }; foreach (var exemption in exemptions) { _adminLogger.Add(LogType.ItemConfigure, LogImpact.Medium, $"{ToPrettyString(user)} set {ToPrettyString(ent)} authorization of {exemption} to {enabled}"); } _deviceNetwork.QueuePacket(ent, null, payload, device: device); } private void UpdateUIState(Entity ent) { var turretStates = new Dictionary(); 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); } }