From c3d7ecace683741d71781707ca41ff451e38f009 Mon Sep 17 00:00:00 2001
From: Flipp Syder <76629141+vulppine@users.noreply.github.com>
Date: Mon, 5 Sep 2022 18:22:39 -0700
Subject: [PATCH] Adds a link limit and UI to device list (#11017)
* adds a link limit to device list
* locale strings
* uhhh what's efcore doing there
* adds a UI for device list on the device
* merge conflict fixing
---
.../NetworkConfiguratorBoundUserInterface.cs | 11 +++-
.../NetworkConfiguratorConfigurationMenu.xaml | 3 +
...tworkConfiguratorConfigurationMenu.xaml.cs | 9 ++-
.../NetworkConfiguratorDeviceList.xaml | 9 +++
.../NetworkConfiguratorDeviceList.xaml.cs | 58 +++++++++++++++++++
.../NetworkConfiguratorListMenu.xaml | 9 +--
.../NetworkConfiguratorListMenu.xaml.cs | 44 +-------------
.../Systems/NetworkConfiguratorSystem.cs | 30 ++++++++--
.../Components/DeviceListComponent.cs | 7 +++
.../NetworkConfiguratorUserInterfaceState.cs | 11 ++++
.../Systems/SharedDeviceListSystem.cs | 26 +++++++--
.../en-US/devices/network-configurator.ftl | 2 +
12 files changed, 156 insertions(+), 63 deletions(-)
create mode 100644 Content.Client/NetworkConfigurator/NetworkConfiguratorDeviceList.xaml
create mode 100644 Content.Client/NetworkConfigurator/NetworkConfiguratorDeviceList.xaml.cs
diff --git a/Content.Client/NetworkConfigurator/NetworkConfiguratorBoundUserInterface.cs b/Content.Client/NetworkConfigurator/NetworkConfiguratorBoundUserInterface.cs
index 168615ca0b..74b2732826 100644
--- a/Content.Client/NetworkConfigurator/NetworkConfiguratorBoundUserInterface.cs
+++ b/Content.Client/NetworkConfigurator/NetworkConfiguratorBoundUserInterface.cs
@@ -75,8 +75,15 @@ public sealed class NetworkConfiguratorBoundUserInterface : BoundUserInterface
{
base.UpdateState(state);
- var castState = (NetworkConfiguratorUserInterfaceState) state;
- _listMenu?.UpdateState(castState);
+ switch (state)
+ {
+ case NetworkConfiguratorUserInterfaceState configState:
+ _listMenu?.UpdateState(configState);
+ break;
+ case DeviceListUserInterfaceState listState:
+ _configurationMenu?.UpdateState(listState);
+ break;
+ }
}
protected override void ReceiveMessage(BoundUserInterfaceMessage message)
diff --git a/Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml b/Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml
index 7be6c47b7a..950bb14604 100644
--- a/Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml
+++ b/Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml
@@ -1,7 +1,9 @@
+
@@ -13,5 +15,6 @@
+
diff --git a/Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml.cs b/Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml.cs
index 41acabc6ba..68c82b355f 100644
--- a/Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml.cs
+++ b/Content.Client/NetworkConfigurator/NetworkConfiguratorConfigurationMenu.xaml.cs
@@ -1,5 +1,6 @@
using Content.Client.Stylesheets;
using Content.Client.UserInterface;
+using Content.Shared.DeviceNetwork;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
@@ -11,7 +12,6 @@ namespace Content.Client.NetworkConfigurator;
[GenerateTypedNameReferences]
public sealed partial class NetworkConfiguratorConfigurationMenu : FancyWindow
{
-
public NetworkConfiguratorConfigurationMenu()
{
RobustXamlLoader.Load(this);
@@ -19,4 +19,11 @@ public sealed partial class NetworkConfiguratorConfigurationMenu : FancyWindow
Clear.StyleClasses.Add(StyleBase.ButtonOpenLeft);
Clear.StyleClasses.Add(StyleNano.StyleClassButtonColorRed);
}
+
+ public void UpdateState(DeviceListUserInterfaceState state)
+ {
+ DeviceList.UpdateState(null, state.DeviceList);
+
+ Count.Text = Loc.GetString("network-configurator-ui-count-label", ("count", state.DeviceList.Count));
+ }
}
diff --git a/Content.Client/NetworkConfigurator/NetworkConfiguratorDeviceList.xaml b/Content.Client/NetworkConfigurator/NetworkConfiguratorDeviceList.xaml
new file mode 100644
index 0000000000..c99ae1e26f
--- /dev/null
+++ b/Content.Client/NetworkConfigurator/NetworkConfiguratorDeviceList.xaml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
diff --git a/Content.Client/NetworkConfigurator/NetworkConfiguratorDeviceList.xaml.cs b/Content.Client/NetworkConfigurator/NetworkConfiguratorDeviceList.xaml.cs
new file mode 100644
index 0000000000..6891faf366
--- /dev/null
+++ b/Content.Client/NetworkConfigurator/NetworkConfiguratorDeviceList.xaml.cs
@@ -0,0 +1,58 @@
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface.Controls;
+
+namespace Content.Client.NetworkConfigurator;
+
+[GenerateTypedNameReferences]
+public sealed partial class NetworkConfiguratorDeviceList : ScrollContainer
+{
+ public void UpdateState(NetworkConfiguratorBoundUserInterface? ui, HashSet<(string address, string name)> devices)
+ {
+ DeviceList.RemoveAllChildren();
+
+ foreach (var device in devices)
+ {
+ DeviceList.AddChild(BuildDeviceListRow(ui, device));
+ }
+ }
+
+ private static BoxContainer BuildDeviceListRow(NetworkConfiguratorBoundUserInterface? ui, (string address, string name) savedDevice)
+ {
+ var row = new BoxContainer()
+ {
+ Orientation = BoxContainer.LayoutOrientation.Horizontal,
+ Margin = new Thickness(8)
+ };
+
+ var name = new Label()
+ {
+ Text = savedDevice.name[..Math.Min(11, savedDevice.name.Length)],
+ SetWidth = 84
+ };
+
+ var address = new Label()
+ {
+ Text = savedDevice.address,
+ HorizontalExpand = true,
+ Align = Label.AlignMode.Center
+ };
+
+ var removeButton = new TextureButton()
+ {
+ StyleClasses = { "CrossButtonRed" },
+ VerticalAlignment = VAlignment.Center,
+ Scale = new Vector2(0.5f, 0.5f)
+ };
+
+ row.AddChild(name);
+ row.AddChild(address);
+
+ if (ui != null)
+ {
+ row.AddChild(removeButton);
+ removeButton.OnPressed += _ => ui.OnRemoveButtonPressed(savedDevice.address);
+ }
+
+ return row;
+ }
+}
diff --git a/Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml b/Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml
index dbbbb35ddb..d00a90a2e7 100644
--- a/Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml
+++ b/Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml
@@ -1,14 +1,9 @@
-
-
-
-
-
-
-
+
diff --git a/Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml.cs b/Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml.cs
index e32db2a519..644deeea1b 100644
--- a/Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml.cs
+++ b/Content.Client/NetworkConfigurator/NetworkConfiguratorListMenu.xaml.cs
@@ -20,48 +20,6 @@ public sealed partial class NetworkConfiguratorListMenu : FancyWindow
public void UpdateState(NetworkConfiguratorUserInterfaceState state)
{
DeviceCountLabel.Text = Loc.GetString("network-configurator-ui-count-label", ("count", state.DeviceList.Count));
- DeviceList.RemoveAllChildren();
-
- foreach (var savedDevice in state.DeviceList)
- {
- DeviceList.AddChild(BuildDeviceListRow(savedDevice));
- }
- }
-
- private BoxContainer BuildDeviceListRow((string address, string name) savedDevice)
- {
- var row = new BoxContainer()
- {
- Orientation = BoxContainer.LayoutOrientation.Horizontal,
- Margin = new Thickness(8)
- };
-
- var name = new Label()
- {
- Text = savedDevice.name[..Math.Min(11, savedDevice.name.Length)],
- SetWidth = 84
- };
-
- var address = new Label()
- {
- Text = savedDevice.address,
- HorizontalExpand = true,
- Align = Label.AlignMode.Center
- };
-
- var removeButton = new TextureButton()
- {
- StyleClasses = { "CrossButtonRed" },
- VerticalAlignment = VAlignment.Center,
- Scale = new Vector2(0.5f, 0.5f)
- };
-
- removeButton.OnPressed += _ => _ui.OnRemoveButtonPressed(savedDevice.address);
-
- row.AddChild(name);
- row.AddChild(address);
- row.AddChild(removeButton);
-
- return row;
+ DeviceList.UpdateState(_ui, state.DeviceList);
}
}
diff --git a/Content.Server/DeviceNetwork/Systems/NetworkConfiguratorSystem.cs b/Content.Server/DeviceNetwork/Systems/NetworkConfiguratorSystem.cs
index 1e01de5046..62306745e0 100644
--- a/Content.Server/DeviceNetwork/Systems/NetworkConfiguratorSystem.cs
+++ b/Content.Server/DeviceNetwork/Systems/NetworkConfiguratorSystem.cs
@@ -222,6 +222,12 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
configurator.ActiveDeviceList = targetUid;
Dirty(configurator);
_uiSystem.GetUiOrNull(configurator.Owner, NetworkConfiguratorUiKey.Configure)?.Open(actor.PlayerSession);
+ _uiSystem.TrySetUiState(
+ configurator.Owner,
+ NetworkConfiguratorUiKey.Configure,
+ new DeviceListUserInterfaceState(
+ _deviceListSystem.GetDeviceList(configurator.ActiveDeviceList.Value)
+ .Select(v => (v.Key, MetaData(v.Value).EntityName)).ToHashSet()));
}
///
@@ -287,26 +293,42 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
if (!component.ActiveDeviceList.HasValue)
return;
+ var result = DeviceListUpdateResult.NoComponent;
switch (args.ButtonKey)
{
case NetworkConfiguratorButtonKey.Set:
- _deviceListSystem.UpdateDeviceList(component.ActiveDeviceList.Value, new HashSet(component.Devices.Values));
+ result = _deviceListSystem.UpdateDeviceList(component.ActiveDeviceList.Value, new HashSet(component.Devices.Values));
break;
case NetworkConfiguratorButtonKey.Add:
- _deviceListSystem.UpdateDeviceList(component.ActiveDeviceList.Value, new HashSet(component.Devices.Values), true);
+ result = _deviceListSystem.UpdateDeviceList(component.ActiveDeviceList.Value, new HashSet(component.Devices.Values), true);
break;
case NetworkConfiguratorButtonKey.Clear:
- _deviceListSystem.UpdateDeviceList(component.ActiveDeviceList.Value, new HashSet());
+ result = _deviceListSystem.UpdateDeviceList(component.ActiveDeviceList.Value, new HashSet());
break;
case NetworkConfiguratorButtonKey.Copy:
component.Devices = _deviceListSystem.GetDeviceList(component.ActiveDeviceList.Value);
UpdateUiState(uid, component);
- break;
+ return;
case NetworkConfiguratorButtonKey.Show:
// This should be done client-side.
// _deviceListSystem.ToggleVisualization(component.ActiveDeviceList.Value);
break;
}
+
+ var resultText = result switch
+ {
+ DeviceListUpdateResult.TooManyDevices => Loc.GetString("network-configurator-too-many-devices"),
+ DeviceListUpdateResult.UpdateOk => Loc.GetString("network-configurator-update-ok"),
+ _ => "error"
+ };
+
+ _popupSystem.PopupCursor(Loc.GetString(resultText), Filter.SinglePlayer(args.Session), PopupType.Medium);
+ _uiSystem.TrySetUiState(
+ component.Owner,
+ NetworkConfiguratorUiKey.Configure,
+ new DeviceListUserInterfaceState(
+ _deviceListSystem.GetDeviceList(component.ActiveDeviceList.Value)
+ .Select(v => (v.Key, MetaData(v.Value).EntityName)).ToHashSet()));
}
// hacky solution related to mapping
diff --git a/Content.Shared/DeviceNetwork/Components/DeviceListComponent.cs b/Content.Shared/DeviceNetwork/Components/DeviceListComponent.cs
index 6fba5e8145..f5c9160a0a 100644
--- a/Content.Shared/DeviceNetwork/Components/DeviceListComponent.cs
+++ b/Content.Shared/DeviceNetwork/Components/DeviceListComponent.cs
@@ -14,6 +14,13 @@ public sealed class DeviceListComponent : Component
[DataField("devices")]
public HashSet Devices = new();
+ ///
+ /// The limit of devices that can be linked to this device list.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("deviceLimit")]
+ public int DeviceLimit = 32;
+
///
/// Whether the device list is used as an allow or deny list
///
diff --git a/Content.Shared/DeviceNetwork/NetworkConfiguratorUserInterfaceState.cs b/Content.Shared/DeviceNetwork/NetworkConfiguratorUserInterfaceState.cs
index 03d44fac66..483b654036 100644
--- a/Content.Shared/DeviceNetwork/NetworkConfiguratorUserInterfaceState.cs
+++ b/Content.Shared/DeviceNetwork/NetworkConfiguratorUserInterfaceState.cs
@@ -12,3 +12,14 @@ public sealed class NetworkConfiguratorUserInterfaceState : BoundUserInterfaceSt
DeviceList = deviceList;
}
}
+
+[Serializable, NetSerializable]
+public sealed class DeviceListUserInterfaceState : BoundUserInterfaceState
+{
+ public readonly HashSet<(string address, string name)> DeviceList;
+
+ public DeviceListUserInterfaceState(HashSet<(string address, string name)> deviceList)
+ {
+ DeviceList = deviceList;
+ }
+}
diff --git a/Content.Shared/DeviceNetwork/Systems/SharedDeviceListSystem.cs b/Content.Shared/DeviceNetwork/Systems/SharedDeviceListSystem.cs
index ada12eebef..28771b43fa 100644
--- a/Content.Shared/DeviceNetwork/Systems/SharedDeviceListSystem.cs
+++ b/Content.Shared/DeviceNetwork/Systems/SharedDeviceListSystem.cs
@@ -18,20 +18,27 @@ public abstract class SharedDeviceListSystem : EntitySystem
/// The devices to store.
/// Whether to merge or replace the devices stored.
/// Device list component
- public void UpdateDeviceList(EntityUid uid, IEnumerable devices, bool merge = false, DeviceListComponent? deviceList = null)
+ public DeviceListUpdateResult UpdateDeviceList(EntityUid uid, IEnumerable devices, bool merge = false, DeviceListComponent? deviceList = null)
{
if (!Resolve(uid, ref deviceList))
- return;
-
- if (!merge)
- deviceList.Devices.Clear();
+ return DeviceListUpdateResult.NoComponent;
+ var newDevices = merge ? new HashSet(deviceList.Devices) : new();
var devicesList = devices.ToList();
- deviceList.Devices.UnionWith(devicesList);
+
+ newDevices.UnionWith(devicesList);
+ if (newDevices.Count > deviceList.DeviceLimit)
+ {
+ return DeviceListUpdateResult.TooManyDevices;
+ }
+
+ deviceList.Devices = newDevices;
RaiseLocalEvent(uid, new DeviceListUpdateEvent(devicesList));
Dirty(deviceList);
+
+ return DeviceListUpdateResult.UpdateOk;
}
public IEnumerable GetAllDevices(EntityUid uid, DeviceListComponent? component = null)
@@ -70,3 +77,10 @@ public sealed class DeviceListUpdateEvent : EntityEventArgs
public List Devices { get; }
}
+
+public enum DeviceListUpdateResult : byte
+{
+ NoComponent,
+ TooManyDevices,
+ UpdateOk
+}
diff --git a/Resources/Locale/en-US/devices/network-configurator.ftl b/Resources/Locale/en-US/devices/network-configurator.ftl
index c3f210de0b..f7d663a6d6 100644
--- a/Resources/Locale/en-US/devices/network-configurator.ftl
+++ b/Resources/Locale/en-US/devices/network-configurator.ftl
@@ -2,6 +2,8 @@
network-configurator-device-saved = Successfully saved network device {$device} with address {$address}!
network-configurator-device-failed = Failed to save network device {$device}! No address assigned!
+network-configurator-too-many-devices = Too many devices stored on this device!
+network-configurator-update-ok = Device storage updated.
network-configurator-device-already-saved = network device: {$device} is already saved.
network-configurator-device-access-denied = Access denied!