diff --git a/Content.Client/NetworkConfigurator/Systems/NetworkConfiguratorSystem.cs b/Content.Client/NetworkConfigurator/Systems/NetworkConfiguratorSystem.cs index 7bd13a12b2..9047d7cc8a 100644 --- a/Content.Client/NetworkConfigurator/Systems/NetworkConfiguratorSystem.cs +++ b/Content.Client/NetworkConfigurator/Systems/NetworkConfiguratorSystem.cs @@ -102,17 +102,6 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem _overlay.RemoveOverlay(overlay); } - // hacky solution related to mapping - public void SetActiveDeviceList(EntityUid tool, EntityUid list, NetworkConfiguratorComponent? component = null) - { - if (!Resolve(tool, ref component)) - { - return; - } - - component.ActiveDeviceList = list; - } - private sealed class StatusControl : Control { private readonly RichTextLabel _label; diff --git a/Content.Server/DeviceNetwork/Components/DeviceNetworkComponent.cs b/Content.Server/DeviceNetwork/Components/DeviceNetworkComponent.cs index 7bd89382bc..3a68fffbcc 100644 --- a/Content.Server/DeviceNetwork/Components/DeviceNetworkComponent.cs +++ b/Content.Server/DeviceNetwork/Components/DeviceNetworkComponent.cs @@ -103,11 +103,17 @@ namespace Content.Server.DeviceNetwork.Components public bool SendBroadcastAttemptEvent = false; /// - /// A list of entities that get sent the when this entity gets deleted.

- /// When a device subscribes to the deletion of another device the entity id of the device being subscribed - /// to also gets saved on the subscribing device. + /// A list of device-lists that this device is on. ///
- [DataField("ShutdownSubscribers")] - public HashSet ShutdownSubscribers = new(); + [DataField] + [Access(typeof(DeviceListSystem))] + public HashSet DeviceLists = new(); + + /// + /// A list of configurators that this device is on. + /// + [DataField] + [Access(typeof(NetworkConfiguratorSystem))] + public HashSet Configurators = new(); } } diff --git a/Content.Server/DeviceNetwork/Systems/DeviceListSystem.cs b/Content.Server/DeviceNetwork/Systems/DeviceListSystem.cs index f3d1231b0f..66c1e36254 100644 --- a/Content.Server/DeviceNetwork/Systems/DeviceListSystem.cs +++ b/Content.Server/DeviceNetwork/Systems/DeviceListSystem.cs @@ -14,22 +14,32 @@ public sealed class DeviceListSystem : SharedDeviceListSystem { private ISawmill _sawmill = default!; - [Dependency] private DeviceNetworkSystem _deviceNetworkSystem = null!; + [Dependency] private readonly NetworkConfiguratorSystem _configurator = default!; public override void Initialize() { base.Initialize(); - SubscribeLocalEvent(OnInit); + SubscribeLocalEvent(OnShutdown); SubscribeLocalEvent(OnBeforeBroadcast); SubscribeLocalEvent(OnBeforePacketSent); - SubscribeLocalEvent(OnDeviceShutdown); SubscribeLocalEvent(OnMapSave); _sawmill = Logger.GetSawmill("devicelist"); } - public void OnInit(EntityUid uid, DeviceListComponent component, ComponentInit args) + private void OnShutdown(EntityUid uid, DeviceListComponent component, ComponentShutdown args) { - Dirty(component); + foreach (var conf in component.Configurators) + { + _configurator.OnDeviceListShutdown(conf, (uid, component)); + } + + var query = GetEntityQuery(); + foreach (var device in component.Devices) + { + if (query.TryGetComponent(device, out var comp)) + comp.DeviceLists.Remove(uid); + } + component.Devices.Clear(); } /// @@ -74,20 +84,6 @@ public sealed class DeviceListSystem : SharedDeviceListSystem return addresses.Contains(address); } - protected override void UpdateShutdownSubscription(EntityUid uid, List newDevices, List oldDevices) - { - foreach (var device in newDevices) - { - _deviceNetworkSystem.SubscribeToDeviceShutdown(uid, device); - } - - var removedDevices = oldDevices.Except(newDevices); - foreach (var device in removedDevices) - { - _deviceNetworkSystem.UnsubscribeFromDeviceShutdown(uid, device); - } - } - /// /// Filters the broadcasts recipient list against the device list as either an allow or deny list depending on the components IsAllowList field /// @@ -119,10 +115,14 @@ public sealed class DeviceListSystem : SharedDeviceListSystem args.Cancel(); } - private void OnDeviceShutdown(EntityUid uid, DeviceListComponent component, ref DeviceShutDownEvent args) + public void OnDeviceShutdown(Entity list, Entity device) { - component.Devices.Remove(args.ShutDownEntityUid); - Dirty(component); + device.Comp.DeviceLists.Remove(list.Owner); + if (!Resolve(list.Owner, ref list.Comp)) + return; + + list.Comp.Devices.Remove(device); + Dirty(list); } private void OnMapSave(BeforeSaveEvent ev) @@ -166,4 +166,57 @@ public sealed class DeviceListSystem : SharedDeviceListSystem toRemove.Clear(); } } + + /// + /// Updates the device list stored on this entity. + /// + /// The entity to update. + /// The devices to store. + /// Whether to merge or replace the devices stored. + /// Device list component + public DeviceListUpdateResult UpdateDeviceList(EntityUid uid, IEnumerable devices, bool merge = false, DeviceListComponent? deviceList = null) + { + if (!Resolve(uid, ref deviceList)) + return DeviceListUpdateResult.NoComponent; + + var list = devices.ToList(); + var newDevices = new HashSet(list); + + if (merge) + newDevices.UnionWith(deviceList.Devices); + + if (newDevices.Count > deviceList.DeviceLimit) + { + return DeviceListUpdateResult.TooManyDevices; + } + + var query = GetEntityQuery(); + var oldDevices = deviceList.Devices.ToList(); + foreach (var device in oldDevices) + { + if (newDevices.Contains(device)) + continue; + + deviceList.Devices.Remove(device); + if (query.TryGetComponent(device, out var comp)) + comp.DeviceLists.Remove(uid); + } + + foreach (var device in newDevices) + { + if (!query.TryGetComponent(device, out var comp)) + continue; + + if (!deviceList.Devices.Add(device)) + continue; + + comp.DeviceLists.Add(uid); + } + + RaiseLocalEvent(uid, new DeviceListUpdateEvent(oldDevices, list)); + + Dirty(uid, deviceList); + + return DeviceListUpdateResult.UpdateOk; + } } diff --git a/Content.Server/DeviceNetwork/Systems/DeviceNetworkSystem.cs b/Content.Server/DeviceNetwork/Systems/DeviceNetworkSystem.cs index d17093c294..83967c9bbd 100644 --- a/Content.Server/DeviceNetwork/Systems/DeviceNetworkSystem.cs +++ b/Content.Server/DeviceNetwork/Systems/DeviceNetworkSystem.cs @@ -6,6 +6,7 @@ using Robust.Shared.Random; using System.Buffers; using System.Diagnostics.CodeAnalysis; using System.Numerics; +using Content.Shared.DeviceNetwork.Components; using Content.Shared.Examine; namespace Content.Server.DeviceNetwork.Systems @@ -20,6 +21,8 @@ namespace Content.Server.DeviceNetwork.Systems [Dependency] private readonly IRobustRandom _random = default!; [Dependency] private readonly IPrototypeManager _protoMan = default!; [Dependency] private readonly SharedTransformSystem _transformSystem = default!; + [Dependency] private readonly DeviceListSystem _deviceLists = default!; + [Dependency] private readonly NetworkConfiguratorSystem _configurator = default!; private readonly Dictionary _networks = new(4); private readonly Queue _queueA = new(); @@ -143,15 +146,14 @@ namespace Content.Server.DeviceNetwork.Systems /// private void OnNetworkShutdown(EntityUid uid, DeviceNetworkComponent component, ComponentShutdown args) { - var eventArgs = new DeviceShutDownEvent(uid); - - foreach (var shutdownSubscriberId in component.ShutdownSubscribers) + foreach (var list in component.DeviceLists) { - RaiseLocalEvent(shutdownSubscriberId, ref eventArgs); + _deviceLists.OnDeviceShutdown(list, (uid, component)); + } - DeviceNetworkComponent? device = null!; - if (Resolve(shutdownSubscriberId, ref device)) - device.ShutdownSubscribers.Remove(uid); + foreach (var list in component.Configurators) + { + _configurator.OnDeviceShutdown(list, (uid, component)); } GetNetwork(component.DeviceNetId).Remove(component); @@ -267,36 +269,6 @@ namespace Content.Server.DeviceNetwork.Systems deviceNet.Add(device); } - public void SubscribeToDeviceShutdown( - EntityUid subscriberId, EntityUid targetId, - DeviceNetworkComponent? subscribingDevice = null, - DeviceNetworkComponent? targetDevice = null) - { - if (subscriberId == targetId) - return; - - if (!Resolve(subscriberId, ref subscribingDevice) || !Resolve(targetId, ref targetDevice)) - return; - - targetDevice.ShutdownSubscribers.Add(subscriberId); - subscribingDevice.ShutdownSubscribers.Add(targetId); - } - - public void UnsubscribeFromDeviceShutdown( - EntityUid subscriberId, EntityUid targetId, - DeviceNetworkComponent? subscribingDevice = null, - DeviceNetworkComponent? targetDevice = null) - { - if (subscriberId == targetId) - return; - - if (!Resolve(subscriberId, ref subscribingDevice) || !Resolve(targetId, ref targetDevice)) - return; - - targetDevice.ShutdownSubscribers.Remove(subscriberId); - subscribingDevice.ShutdownSubscribers.Remove(targetId); - } - /// /// Try to find a device on a network using its address. /// @@ -481,11 +453,4 @@ namespace Content.Server.DeviceNetwork.Systems Data = data; } } - - /// - /// Gets raised on entities that subscribed to shutdown event of the shut down entity - /// - /// The entity that was shut down - [ByRefEvent] - public readonly record struct DeviceShutDownEvent(EntityUid ShutDownEntityUid); } diff --git a/Content.Server/DeviceNetwork/Systems/NetworkConfiguratorSystem.cs b/Content.Server/DeviceNetwork/Systems/NetworkConfiguratorSystem.cs index 4deb08ec3d..fefe85ce81 100644 --- a/Content.Server/DeviceNetwork/Systems/NetworkConfiguratorSystem.cs +++ b/Content.Server/DeviceNetwork/Systems/NetworkConfiguratorSystem.cs @@ -43,6 +43,7 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem base.Initialize(); SubscribeLocalEvent(OnMapInit); + SubscribeLocalEvent(OnShutdown); //Interaction SubscribeLocalEvent(AfterInteract); //TODO: Replace with utility verb? @@ -66,6 +67,15 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem SubscribeLocalEvent(OnComponentRemoved); } + private void OnShutdown(EntityUid uid, NetworkConfiguratorComponent component, ComponentShutdown args) + { + ClearDevices(uid, component); + + if (TryComp(component.ActiveDeviceList, out DeviceListComponent? list)) + list.Configurators.Remove(uid); + component.ActiveDeviceList = null; + } + public override void Update(float frameTime) { base.Update(frameTime); @@ -85,7 +95,6 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem private void OnMapInit(EntityUid uid, NetworkConfiguratorComponent component, MapInitEvent args) { - component.Devices.Clear(); UpdateListUiState(uid, component); } @@ -131,6 +140,7 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem return; } + device.Configurators.Add(configuratorUid); configurator.Devices.Add(address, targetUid.Value); _popupSystem.PopupCursor(Loc.GetString("network-configurator-device-saved", ("address", device.Address), ("device", targetUid)), userUid, PopupType.Medium); @@ -462,14 +472,21 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem /// private void OpenDeviceListUi(EntityUid configuratorUid, EntityUid? targetUid, EntityUid userUid, NetworkConfiguratorComponent configurator) { + if (configurator.ActiveDeviceLink == targetUid) + return; + if (Delay(configurator)) return; if (!targetUid.HasValue || !TryComp(userUid, out ActorComponent? actor) || !AccessCheck(targetUid.Value, userUid, configurator)) return; + if (!TryComp(targetUid, out DeviceListComponent? list)) + return; + + list.Configurators.Add(configuratorUid); configurator.ActiveDeviceList = targetUid; - Dirty(configurator); + Dirty(configuratorUid, configurator); if (!_uiSystem.TryGetUi(configuratorUid, NetworkConfiguratorUiKey.Configure, out var bui)) return; @@ -516,6 +533,10 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem private void OnUiClosed(EntityUid uid, NetworkConfiguratorComponent component, BoundUIClosedEvent args) { component.ActiveDeviceList = null; + if (TryComp(component.ActiveDeviceList, out DeviceListComponent? list)) + { + list.Configurators.Remove(uid); + } if (args.UiKey is NetworkConfiguratorUiKey.Link) { @@ -524,15 +545,28 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem } } + public void OnDeviceListShutdown(Entity conf, Entity list) + { + list.Comp.Configurators.Remove(conf.Owner); + if (Resolve(conf.Owner, ref conf.Comp)) + conf.Comp.ActiveDeviceList = null; + } + /// /// Removes a device from the saved devices list /// private void OnRemoveDevice(EntityUid uid, NetworkConfiguratorComponent component, NetworkConfiguratorRemoveDeviceMessage args) { if (component.Devices.TryGetValue(args.Address, out var removedDevice) && args.Session.AttachedEntity != null) + { _adminLogger.Add(LogType.DeviceLinking, LogImpact.Low, $"{ToPrettyString(args.Session.AttachedEntity.Value):actor} removed buffered device {ToPrettyString(removedDevice):subject} from {ToPrettyString(uid):tool}"); + } + component.Devices.Remove(args.Address); + if (TryComp(removedDevice, out DeviceNetworkComponent? device)) + device.Configurators.Remove(uid); + UpdateListUiState(uid, component); } @@ -544,10 +578,24 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem if (args.Session.AttachedEntity != null) _adminLogger.Add(LogType.DeviceLinking, LogImpact.Low, $"{ToPrettyString(args.Session.AttachedEntity.Value):actor} cleared buffered devices from {ToPrettyString(uid):tool}"); - component.Devices.Clear(); + + + ClearDevices(uid, component); UpdateListUiState(uid, component); } + private void ClearDevices(EntityUid uid, NetworkConfiguratorComponent component) + { + var query = GetEntityQuery(); + foreach (var device in component.Devices.Values) + { + if (query.TryGetComponent(device, out var comp)) + comp.Configurators.Remove(uid); + } + + component.Devices.Clear(); + } + private void OnClearLinks(EntityUid uid, NetworkConfiguratorComponent configurator, NetworkConfiguratorClearLinksMessage args) { if (!configurator.ActiveDeviceLink.HasValue || !configurator.DeviceLinkTarget.HasValue) @@ -702,7 +750,18 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem if (args.Session.AttachedEntity != null) _adminLogger.Add(LogType.DeviceLinking, LogImpact.Low, $"{ToPrettyString(args.Session.AttachedEntity.Value):actor} copied devices from {ToPrettyString(component.ActiveDeviceList.Value):subject} to {ToPrettyString(uid):tool}"); - component.Devices = _deviceListSystem.GetDeviceList(component.ActiveDeviceList.Value); + + ClearDevices(uid, component); + + var query = GetEntityQuery(); + foreach (var (addr, device) in _deviceListSystem.GetDeviceList(component.ActiveDeviceList.Value)) + { + if (query.TryGetComponent(device, out var comp)) + { + component.Devices[addr] = device; + comp.Configurators.Add(uid); + } + } UpdateListUiState(uid, component); return; case NetworkConfiguratorButtonKey.Show: @@ -725,6 +784,21 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem .Select(v => (v.Key, MetaData(v.Value).EntityName)).ToHashSet())); } + public void OnDeviceShutdown(Entity conf, Entity device) + { + device.Comp.Configurators.Remove(conf.Owner); + if (!Resolve(conf.Owner, ref conf.Comp)) + return; + + foreach (var (addr, dev) in conf.Comp.Devices) + { + if (device.Owner == dev) + conf.Comp.Devices.Remove(addr); + } + + UpdateListUiState(conf, conf.Comp); + } + private void OnUiOpenAttempt(EntityUid uid, NetworkConfiguratorComponent configurator, ActivatableUIOpenAttemptEvent args) { if (configurator.LinkModeActive) diff --git a/Content.Shared/DeviceNetwork/Components/DeviceListComponent.cs b/Content.Shared/DeviceNetwork/Components/DeviceListComponent.cs index 8221710292..98f177c0f3 100644 --- a/Content.Shared/DeviceNetwork/Components/DeviceListComponent.cs +++ b/Content.Shared/DeviceNetwork/Components/DeviceListComponent.cs @@ -33,4 +33,7 @@ public sealed partial class DeviceListComponent : Component [ViewVariables(VVAccess.ReadWrite)] [DataField, AutoNetworkedField] public bool HandleIncomingPackets; + + [DataField, Access(typeof(SharedNetworkConfiguratorSystem))] + public HashSet Configurators = new(); } diff --git a/Content.Shared/DeviceNetwork/Components/NetworkConfiguratorComponent.cs b/Content.Shared/DeviceNetwork/Components/NetworkConfiguratorComponent.cs index 7202b803f8..27c74a9640 100644 --- a/Content.Shared/DeviceNetwork/Components/NetworkConfiguratorComponent.cs +++ b/Content.Shared/DeviceNetwork/Components/NetworkConfiguratorComponent.cs @@ -10,6 +10,7 @@ namespace Content.Shared.DeviceNetwork.Components; [Access(typeof(SharedNetworkConfiguratorSystem))] public sealed partial class NetworkConfiguratorComponent : Component { + // AAAAA ALL OF THESE FAA /// /// Determines whether the configurator is in linking mode or list mode /// @@ -21,19 +22,19 @@ public sealed partial class NetworkConfiguratorComponent : Component /// The entity containing a this configurator is currently interacting with /// [DataField, AutoNetworkedField] - public EntityUid? ActiveDeviceList; + public EntityUid? ActiveDeviceList { get; set; } /// /// The entity containing a or this configurator is currently interacting with.
/// If this is set the configurator is in linking mode. ///
- [DataField] + // TODO handle device deletion public EntityUid? ActiveDeviceLink; /// /// The target device this configurator is currently linking with the /// - [DataField] + // TODO handle device deletion public EntityUid? DeviceLinkTarget; /// diff --git a/Content.Shared/DeviceNetwork/Systems/SharedDeviceListSystem.cs b/Content.Shared/DeviceNetwork/Systems/SharedDeviceListSystem.cs index a15d942ad6..2ff3c2daad 100644 --- a/Content.Shared/DeviceNetwork/Systems/SharedDeviceListSystem.cs +++ b/Content.Shared/DeviceNetwork/Systems/SharedDeviceListSystem.cs @@ -5,39 +5,6 @@ namespace Content.Shared.DeviceNetwork.Systems; public abstract class SharedDeviceListSystem : EntitySystem { - /// - /// Updates the device list stored on this entity. - /// - /// The entity to update. - /// The devices to store. - /// Whether to merge or replace the devices stored. - /// Device list component - public DeviceListUpdateResult UpdateDeviceList(EntityUid uid, IEnumerable devices, bool merge = false, DeviceListComponent? deviceList = null) - { - if (!Resolve(uid, ref deviceList)) - return DeviceListUpdateResult.NoComponent; - - var oldDevices = deviceList.Devices.ToList(); - var newDevices = merge ? new HashSet(deviceList.Devices) : new(); - var devicesList = devices.ToList(); - - newDevices.UnionWith(devicesList); - if (newDevices.Count > deviceList.DeviceLimit) - { - return DeviceListUpdateResult.TooManyDevices; - } - - deviceList.Devices = newDevices; - - UpdateShutdownSubscription(uid, devicesList, oldDevices); - - RaiseLocalEvent(uid, new DeviceListUpdateEvent(oldDevices, devicesList)); - - Dirty(deviceList); - - return DeviceListUpdateResult.UpdateOk; - } - public IEnumerable GetAllDevices(EntityUid uid, DeviceListComponent? component = null) { if (!Resolve(uid, ref component)) @@ -46,10 +13,6 @@ public abstract class SharedDeviceListSystem : EntitySystem } return component.Devices; } - - protected virtual void UpdateShutdownSubscription(EntityUid uid, List devicesList, List oldDevices) - { - } } public sealed class DeviceListUpdateEvent : EntityEventArgs