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
This commit is contained in:
@@ -75,8 +75,15 @@ public sealed class NetworkConfiguratorBoundUserInterface : BoundUserInterface
|
|||||||
{
|
{
|
||||||
base.UpdateState(state);
|
base.UpdateState(state);
|
||||||
|
|
||||||
var castState = (NetworkConfiguratorUserInterfaceState) state;
|
switch (state)
|
||||||
_listMenu?.UpdateState(castState);
|
{
|
||||||
|
case NetworkConfiguratorUserInterfaceState configState:
|
||||||
|
_listMenu?.UpdateState(configState);
|
||||||
|
break;
|
||||||
|
case DeviceListUserInterfaceState listState:
|
||||||
|
_configurationMenu?.UpdateState(listState);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ReceiveMessage(BoundUserInterfaceMessage message)
|
protected override void ReceiveMessage(BoundUserInterfaceMessage message)
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
<ui:FancyWindow xmlns="https://spacestation14.io"
|
<ui:FancyWindow xmlns="https://spacestation14.io"
|
||||||
xmlns:ui="clr-namespace:Content.Client.UserInterface"
|
xmlns:ui="clr-namespace:Content.Client.UserInterface"
|
||||||
|
xmlns:networkConfigurator="clr-namespace:Content.Client.NetworkConfigurator"
|
||||||
Title="Network Configurator" MinSize="350 100">
|
Title="Network Configurator" MinSize="350 100">
|
||||||
<BoxContainer Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True">
|
<BoxContainer Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True">
|
||||||
|
<networkConfigurator:NetworkConfiguratorDeviceList Name="DeviceList" MinHeight="500" />
|
||||||
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" Margin="8 8 8 1">
|
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" Margin="8 8 8 1">
|
||||||
<Button Name="Set" Text="Set" Access="Public" ToolTip="{Loc 'network-configurator-tooltip-set'}" HorizontalExpand="True" StyleClasses="ButtonSquare"/>
|
<Button Name="Set" Text="Set" Access="Public" ToolTip="{Loc 'network-configurator-tooltip-set'}" HorizontalExpand="True" StyleClasses="ButtonSquare"/>
|
||||||
<Button Name="Add" Text="Add" Access="Public" ToolTip="{Loc 'network-configurator-tooltip-add'}" HorizontalExpand="True" StyleClasses="ButtonSquare"/>
|
<Button Name="Add" Text="Add" Access="Public" ToolTip="{Loc 'network-configurator-tooltip-add'}" HorizontalExpand="True" StyleClasses="ButtonSquare"/>
|
||||||
@@ -13,5 +15,6 @@
|
|||||||
<Button Name="Copy" Text="Copy" Access="Public" ToolTip="{Loc 'network-configurator-tooltip-copy'}" HorizontalExpand="True" StyleClasses="OpenRight"/>
|
<Button Name="Copy" Text="Copy" Access="Public" ToolTip="{Loc 'network-configurator-tooltip-copy'}" HorizontalExpand="True" StyleClasses="OpenRight"/>
|
||||||
<Button Name="Show" Text="Show" Access="Public" ToggleMode="True" ToolTip="{Loc 'network-configurator-tooltip-show'}" HorizontalExpand="True" StyleClasses="ButtonSquare"/>
|
<Button Name="Show" Text="Show" Access="Public" ToggleMode="True" ToolTip="{Loc 'network-configurator-tooltip-show'}" HorizontalExpand="True" StyleClasses="ButtonSquare"/>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
|
<Label Name="Count" HorizontalAlignment="Right" />
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
</ui:FancyWindow>
|
</ui:FancyWindow>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using Content.Client.Stylesheets;
|
using Content.Client.Stylesheets;
|
||||||
using Content.Client.UserInterface;
|
using Content.Client.UserInterface;
|
||||||
|
using Content.Shared.DeviceNetwork;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Client.UserInterface.CustomControls;
|
using Robust.Client.UserInterface.CustomControls;
|
||||||
@@ -11,7 +12,6 @@ namespace Content.Client.NetworkConfigurator;
|
|||||||
[GenerateTypedNameReferences]
|
[GenerateTypedNameReferences]
|
||||||
public sealed partial class NetworkConfiguratorConfigurationMenu : FancyWindow
|
public sealed partial class NetworkConfiguratorConfigurationMenu : FancyWindow
|
||||||
{
|
{
|
||||||
|
|
||||||
public NetworkConfiguratorConfigurationMenu()
|
public NetworkConfiguratorConfigurationMenu()
|
||||||
{
|
{
|
||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
@@ -19,4 +19,11 @@ public sealed partial class NetworkConfiguratorConfigurationMenu : FancyWindow
|
|||||||
Clear.StyleClasses.Add(StyleBase.ButtonOpenLeft);
|
Clear.StyleClasses.Add(StyleBase.ButtonOpenLeft);
|
||||||
Clear.StyleClasses.Add(StyleNano.StyleClassButtonColorRed);
|
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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<ScrollContainer xmlns="https://spacestation14.io"
|
||||||
|
HorizontalExpand="True"
|
||||||
|
VerticalExpand="True">
|
||||||
|
<Control VerticalExpand="True">
|
||||||
|
<PanelContainer StyleClasses="PanelBackgroundBaseDark"></PanelContainer>
|
||||||
|
<BoxContainer Orientation="Vertical" Name="DeviceList" VerticalExpand="True" SeparationOverride="4">
|
||||||
|
</BoxContainer>
|
||||||
|
</Control>
|
||||||
|
</ScrollContainer>
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,9 @@
|
|||||||
<ui:FancyWindow xmlns="https://spacestation14.io"
|
<ui:FancyWindow xmlns="https://spacestation14.io"
|
||||||
xmlns:ui="clr-namespace:Content.Client.UserInterface"
|
xmlns:ui="clr-namespace:Content.Client.UserInterface"
|
||||||
|
xmlns:networkConfigurator="clr-namespace:Content.Client.NetworkConfigurator"
|
||||||
Title="Network Configurator" MinSize="220 400">
|
Title="Network Configurator" MinSize="220 400">
|
||||||
<BoxContainer Orientation="Vertical" VerticalExpand="True">
|
<BoxContainer Orientation="Vertical" VerticalExpand="True">
|
||||||
<ScrollContainer HorizontalExpand="True" VerticalExpand="True">
|
<networkConfigurator:NetworkConfiguratorDeviceList Name="DeviceList" />
|
||||||
<Control VerticalExpand="True">
|
|
||||||
<PanelContainer StyleClasses="PanelBackgroundBaseDark"></PanelContainer>
|
|
||||||
<BoxContainer Orientation="Vertical" Name="DeviceList" VerticalExpand="True" SeparationOverride="4">
|
|
||||||
</BoxContainer>
|
|
||||||
</Control>
|
|
||||||
</ScrollContainer>
|
|
||||||
<BoxContainer Orientation="Horizontal" Margin="8 8 8 8">
|
<BoxContainer Orientation="Horizontal" Margin="8 8 8 8">
|
||||||
<Label Name="DeviceCountLabel" Margin="16 0 0 0" MaxWidth="64"></Label>
|
<Label Name="DeviceCountLabel" Margin="16 0 0 0" MaxWidth="64"></Label>
|
||||||
<Control HorizontalExpand="True" />
|
<Control HorizontalExpand="True" />
|
||||||
|
|||||||
@@ -20,48 +20,6 @@ public sealed partial class NetworkConfiguratorListMenu : FancyWindow
|
|||||||
public void UpdateState(NetworkConfiguratorUserInterfaceState state)
|
public void UpdateState(NetworkConfiguratorUserInterfaceState state)
|
||||||
{
|
{
|
||||||
DeviceCountLabel.Text = Loc.GetString("network-configurator-ui-count-label", ("count", state.DeviceList.Count));
|
DeviceCountLabel.Text = Loc.GetString("network-configurator-ui-count-label", ("count", state.DeviceList.Count));
|
||||||
DeviceList.RemoveAllChildren();
|
DeviceList.UpdateState(_ui, state.DeviceList);
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -222,6 +222,12 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
|||||||
configurator.ActiveDeviceList = targetUid;
|
configurator.ActiveDeviceList = targetUid;
|
||||||
Dirty(configurator);
|
Dirty(configurator);
|
||||||
_uiSystem.GetUiOrNull(configurator.Owner, NetworkConfiguratorUiKey.Configure)?.Open(actor.PlayerSession);
|
_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()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -287,26 +293,42 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
|||||||
if (!component.ActiveDeviceList.HasValue)
|
if (!component.ActiveDeviceList.HasValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
var result = DeviceListUpdateResult.NoComponent;
|
||||||
switch (args.ButtonKey)
|
switch (args.ButtonKey)
|
||||||
{
|
{
|
||||||
case NetworkConfiguratorButtonKey.Set:
|
case NetworkConfiguratorButtonKey.Set:
|
||||||
_deviceListSystem.UpdateDeviceList(component.ActiveDeviceList.Value, new HashSet<EntityUid>(component.Devices.Values));
|
result = _deviceListSystem.UpdateDeviceList(component.ActiveDeviceList.Value, new HashSet<EntityUid>(component.Devices.Values));
|
||||||
break;
|
break;
|
||||||
case NetworkConfiguratorButtonKey.Add:
|
case NetworkConfiguratorButtonKey.Add:
|
||||||
_deviceListSystem.UpdateDeviceList(component.ActiveDeviceList.Value, new HashSet<EntityUid>(component.Devices.Values), true);
|
result = _deviceListSystem.UpdateDeviceList(component.ActiveDeviceList.Value, new HashSet<EntityUid>(component.Devices.Values), true);
|
||||||
break;
|
break;
|
||||||
case NetworkConfiguratorButtonKey.Clear:
|
case NetworkConfiguratorButtonKey.Clear:
|
||||||
_deviceListSystem.UpdateDeviceList(component.ActiveDeviceList.Value, new HashSet<EntityUid>());
|
result = _deviceListSystem.UpdateDeviceList(component.ActiveDeviceList.Value, new HashSet<EntityUid>());
|
||||||
break;
|
break;
|
||||||
case NetworkConfiguratorButtonKey.Copy:
|
case NetworkConfiguratorButtonKey.Copy:
|
||||||
component.Devices = _deviceListSystem.GetDeviceList(component.ActiveDeviceList.Value);
|
component.Devices = _deviceListSystem.GetDeviceList(component.ActiveDeviceList.Value);
|
||||||
UpdateUiState(uid, component);
|
UpdateUiState(uid, component);
|
||||||
break;
|
return;
|
||||||
case NetworkConfiguratorButtonKey.Show:
|
case NetworkConfiguratorButtonKey.Show:
|
||||||
// This should be done client-side.
|
// This should be done client-side.
|
||||||
// _deviceListSystem.ToggleVisualization(component.ActiveDeviceList.Value);
|
// _deviceListSystem.ToggleVisualization(component.ActiveDeviceList.Value);
|
||||||
break;
|
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
|
// hacky solution related to mapping
|
||||||
|
|||||||
@@ -14,6 +14,13 @@ public sealed class DeviceListComponent : Component
|
|||||||
[DataField("devices")]
|
[DataField("devices")]
|
||||||
public HashSet<EntityUid> Devices = new();
|
public HashSet<EntityUid> Devices = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The limit of devices that can be linked to this device list.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
[DataField("deviceLimit")]
|
||||||
|
public int DeviceLimit = 32;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the device list is used as an allow or deny list
|
/// Whether the device list is used as an allow or deny list
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -12,3 +12,14 @@ public sealed class NetworkConfiguratorUserInterfaceState : BoundUserInterfaceSt
|
|||||||
DeviceList = deviceList;
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,20 +18,27 @@ public abstract class SharedDeviceListSystem : EntitySystem
|
|||||||
/// <param name="devices">The devices to store.</param>
|
/// <param name="devices">The devices to store.</param>
|
||||||
/// <param name="merge">Whether to merge or replace the devices stored.</param>
|
/// <param name="merge">Whether to merge or replace the devices stored.</param>
|
||||||
/// <param name="deviceList">Device list component</param>
|
/// <param name="deviceList">Device list component</param>
|
||||||
public void UpdateDeviceList(EntityUid uid, IEnumerable<EntityUid> devices, bool merge = false, DeviceListComponent? deviceList = null)
|
public DeviceListUpdateResult UpdateDeviceList(EntityUid uid, IEnumerable<EntityUid> devices, bool merge = false, DeviceListComponent? deviceList = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref deviceList))
|
if (!Resolve(uid, ref deviceList))
|
||||||
return;
|
return DeviceListUpdateResult.NoComponent;
|
||||||
|
|
||||||
if (!merge)
|
|
||||||
deviceList.Devices.Clear();
|
|
||||||
|
|
||||||
|
var newDevices = merge ? new HashSet<EntityUid>(deviceList.Devices) : new();
|
||||||
var devicesList = devices.ToList();
|
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));
|
RaiseLocalEvent(uid, new DeviceListUpdateEvent(devicesList));
|
||||||
|
|
||||||
Dirty(deviceList);
|
Dirty(deviceList);
|
||||||
|
|
||||||
|
return DeviceListUpdateResult.UpdateOk;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<EntityUid> GetAllDevices(EntityUid uid, DeviceListComponent? component = null)
|
public IEnumerable<EntityUid> GetAllDevices(EntityUid uid, DeviceListComponent? component = null)
|
||||||
@@ -70,3 +77,10 @@ public sealed class DeviceListUpdateEvent : EntityEventArgs
|
|||||||
|
|
||||||
public List<EntityUid> Devices { get; }
|
public List<EntityUid> Devices { get; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum DeviceListUpdateResult : byte
|
||||||
|
{
|
||||||
|
NoComponent,
|
||||||
|
TooManyDevices,
|
||||||
|
UpdateOk
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
network-configurator-device-saved = Successfully saved network device {$device} with address {$address}!
|
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-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-already-saved = network device: {$device} is already saved.
|
||||||
network-configurator-device-access-denied = Access denied!
|
network-configurator-device-access-denied = Access denied!
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user