Device Linking and better linking ui (#13645)
Co-authored-by: AJCM-git <60196617+AJCM-git@users.noreply.github.com> Co-authored-by: Visne <39844191+Visne@users.noreply.github.com> Co-authored-by: ElectroJr <leonsfriedrich@gmail.com> Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
using Content.Shared.DeviceNetwork;
|
using Content.Client.NetworkConfigurator.Systems;
|
||||||
using JetBrains.Annotations;
|
using Content.Shared.DeviceNetwork;
|
||||||
using Robust.Client.GameObjects;
|
using Robust.Client.GameObjects;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
|
||||||
@@ -8,17 +8,18 @@ namespace Content.Client.NetworkConfigurator;
|
|||||||
public sealed class NetworkConfiguratorBoundUserInterface : BoundUserInterface
|
public sealed class NetworkConfiguratorBoundUserInterface : BoundUserInterface
|
||||||
{
|
{
|
||||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||||
|
|
||||||
private NetworkConfiguratorListMenu? _listMenu;
|
private NetworkConfiguratorListMenu? _listMenu;
|
||||||
private NetworkConfiguratorConfigurationMenu? _configurationMenu;
|
private NetworkConfiguratorConfigurationMenu? _configurationMenu;
|
||||||
|
private NetworkConfiguratorLinkMenu? _linkMenu;
|
||||||
|
|
||||||
private NetworkConfiguratorSystem _netConfig;
|
private NetworkConfiguratorSystem _netConfig;
|
||||||
private DeviceListSystem _deviceList;
|
|
||||||
|
|
||||||
public NetworkConfiguratorBoundUserInterface(ClientUserInterfaceComponent owner, Enum uiKey) : base(owner, uiKey)
|
public NetworkConfiguratorBoundUserInterface(ClientUserInterfaceComponent owner, Enum uiKey) : base(owner, uiKey)
|
||||||
{
|
{
|
||||||
IoCManager.InjectDependencies(this);
|
IoCManager.InjectDependencies(this);
|
||||||
|
|
||||||
_netConfig = _entityManager.System<NetworkConfiguratorSystem>();
|
_netConfig = _entityManager.System<NetworkConfiguratorSystem>();
|
||||||
_deviceList = _entityManager.System<DeviceListSystem>();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnRemoveButtonPressed(string address)
|
public void OnRemoveButtonPressed(string address)
|
||||||
@@ -36,7 +37,7 @@ public sealed class NetworkConfiguratorBoundUserInterface : BoundUserInterface
|
|||||||
_listMenu = new NetworkConfiguratorListMenu(this);
|
_listMenu = new NetworkConfiguratorListMenu(this);
|
||||||
_listMenu.OnClose += Close;
|
_listMenu.OnClose += Close;
|
||||||
_listMenu.ClearButton.OnPressed += _ => OnClearButtonPressed();
|
_listMenu.ClearButton.OnPressed += _ => OnClearButtonPressed();
|
||||||
_listMenu.OpenCentered();
|
_listMenu.OpenCenteredRight();
|
||||||
break;
|
break;
|
||||||
case NetworkConfiguratorUiKey.Configure:
|
case NetworkConfiguratorUiKey.Configure:
|
||||||
_configurationMenu = new NetworkConfiguratorConfigurationMenu();
|
_configurationMenu = new NetworkConfiguratorConfigurationMenu();
|
||||||
@@ -50,6 +51,11 @@ public sealed class NetworkConfiguratorBoundUserInterface : BoundUserInterface
|
|||||||
_configurationMenu.Show.Pressed = _netConfig.ConfiguredListIsTracked(Owner.Owner);
|
_configurationMenu.Show.Pressed = _netConfig.ConfiguredListIsTracked(Owner.Owner);
|
||||||
_configurationMenu.OpenCentered();
|
_configurationMenu.OpenCentered();
|
||||||
break;
|
break;
|
||||||
|
case NetworkConfiguratorUiKey.Link:
|
||||||
|
_linkMenu = new NetworkConfiguratorLinkMenu(this);
|
||||||
|
_linkMenu.OnClose += Close;
|
||||||
|
_linkMenu.OpenCentered();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,6 +76,9 @@ public sealed class NetworkConfiguratorBoundUserInterface : BoundUserInterface
|
|||||||
case DeviceListUserInterfaceState listState:
|
case DeviceListUserInterfaceState listState:
|
||||||
_configurationMenu?.UpdateState(listState);
|
_configurationMenu?.UpdateState(listState);
|
||||||
break;
|
break;
|
||||||
|
case DeviceLinkUserInterfaceState linkState:
|
||||||
|
_linkMenu?.UpdateState(linkState);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||||
xmlns:networkConfigurator="clr-namespace:Content.Client.NetworkConfigurator"
|
xmlns:networkConfigurator="clr-namespace:Content.Client.NetworkConfigurator"
|
||||||
Title="Network Configurator" MinSize="350 100">
|
Title="{Loc 'network-configurator-title-device-configuration'}" MinSize="350 100">
|
||||||
<BoxContainer Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True">
|
<BoxContainer Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True">
|
||||||
<networkConfigurator:NetworkConfiguratorDeviceList Name="DeviceList" MinHeight="500" />
|
<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">
|
||||||
@@ -15,6 +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" />
|
<Label Name="Count" StyleClasses="LabelSubText" HorizontalAlignment="Right" Margin="0 0 12 8"/>
|
||||||
</BoxContainer>
|
</BoxContainer>
|
||||||
</controls:FancyWindow>
|
</controls:FancyWindow>
|
||||||
|
|||||||
@@ -0,0 +1,47 @@
|
|||||||
|
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||||
|
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||||
|
xmlns:networkConfigurator="clr-namespace:Content.Client.NetworkConfigurator"
|
||||||
|
Title="Network Configurator" MinSize="620 400" RectClipContent="True">
|
||||||
|
<BoxContainer Orientation="Vertical" VerticalExpand="True">
|
||||||
|
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||||
|
<Label Margin="12 0" Text="{Loc signal-port-selector-help}"/>
|
||||||
|
</BoxContainer>
|
||||||
|
<Control VerticalExpand="True" HorizontalExpand="True" Margin="12 6 12 0">
|
||||||
|
<PanelContainer Name="MainPanel" HorizontalExpand="False" VerticalExpand="True" />
|
||||||
|
<ScrollContainer HorizontalExpand="True" VerticalExpand="True" HScrollEnabled="True">
|
||||||
|
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" VerticalExpand="True" Margin="6">
|
||||||
|
<BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.3">
|
||||||
|
<RichTextLabel Name="HeaderLeft"/>
|
||||||
|
<BoxContainer Name="ButtonContainerLeft" Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True"/>
|
||||||
|
</BoxContainer>
|
||||||
|
<BoxContainer Name="MiddleContainer" Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True" SizeFlagsStretchRatio="0.2"/>
|
||||||
|
<BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.3">
|
||||||
|
<RichTextLabel Name="HeaderRight"/>
|
||||||
|
<BoxContainer Name="ButtonContainerRight" Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True"/>
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</ScrollContainer>
|
||||||
|
</Control>
|
||||||
|
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" Margin="12 4">
|
||||||
|
<BoxContainer Orientation="Horizontal">
|
||||||
|
<Button Name="ButtonClear" SetHeight="32" StyleClasses="OpenRight" Text="{Loc signal-port-selector-menu-clear}"/>
|
||||||
|
<Button Name="ButtonLinkDefault" SetHeight="32" StyleClasses="OpenLeft" Text="{Loc signal-port-selector-menu-link-defaults}"/>
|
||||||
|
</BoxContainer>
|
||||||
|
<Control HorizontalExpand="True"/>
|
||||||
|
<Control>
|
||||||
|
<Button Name="ButtonOk" MinHeight="26" StyleClasses="ButtonColorGreen" Text="{Loc signal-port-selector-menu-done}"></Button>
|
||||||
|
</Control>
|
||||||
|
</BoxContainer>
|
||||||
|
<Control SetHeight="28" Margin="1 0 2 1">
|
||||||
|
<PanelContainer Name="FooterPanel"></PanelContainer>
|
||||||
|
<BoxContainer Name="ContentFooter" HorizontalExpand="True" SetHeight="28">
|
||||||
|
<Label Text="Net#Link ™" VerticalAlignment="Center" Margin="6 0" StyleClasses="PDAContentFooterText"/>
|
||||||
|
<Label Name="AddressLabel" VerticalAlignment="Center" HorizontalAlignment="Right" Margin="6 0" StyleClasses="PDAContentFooterText"/>
|
||||||
|
<Control HorizontalExpand="True"/>
|
||||||
|
<Label Name="FromAddressLabel" Margin="6 0" StyleClasses="PDAContentFooterText"/>
|
||||||
|
<Label SetWidth="25" StyleClasses="PDAContentFooterText" Align="Center" Text="➝"/><!--Turn this into an arrow texture-->
|
||||||
|
<Label Name="ToAddressLabel" Margin="6 0" StyleClasses="PDAContentFooterText"/>
|
||||||
|
</BoxContainer>
|
||||||
|
</Control>
|
||||||
|
</BoxContainer>
|
||||||
|
</controls:FancyWindow>
|
||||||
@@ -0,0 +1,221 @@
|
|||||||
|
using Content.Client.UserInterface.Controls;
|
||||||
|
using Content.Shared.DeviceLinking;
|
||||||
|
using Content.Shared.DeviceNetwork;
|
||||||
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.Graphics;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Vector2 = Robust.Shared.Maths.Vector2;
|
||||||
|
|
||||||
|
namespace Content.Client.NetworkConfigurator;
|
||||||
|
|
||||||
|
[GenerateTypedNameReferences]
|
||||||
|
public sealed partial class NetworkConfiguratorLinkMenu : FancyWindow
|
||||||
|
{
|
||||||
|
private const string PanelBgColor = "#202023";
|
||||||
|
|
||||||
|
private readonly LinksRender _links;
|
||||||
|
|
||||||
|
|
||||||
|
private readonly List<SourcePortPrototype> _sources = new();
|
||||||
|
|
||||||
|
private readonly List<SinkPortPrototype> _sinks = new();
|
||||||
|
|
||||||
|
private readonly NetworkConfiguratorBoundUserInterface _userInterface;
|
||||||
|
|
||||||
|
private (ButtonPosition position, string id, int index)? _selectedButton;
|
||||||
|
|
||||||
|
private List<(string left, string right)>? _defaults;
|
||||||
|
|
||||||
|
public NetworkConfiguratorLinkMenu(NetworkConfiguratorBoundUserInterface userInterface)
|
||||||
|
{
|
||||||
|
_userInterface = userInterface;
|
||||||
|
RobustXamlLoader.Load(this);
|
||||||
|
|
||||||
|
var footerStyleBox = new StyleBoxFlat()
|
||||||
|
{
|
||||||
|
BorderThickness = new Thickness(0, 2, 0, 0),
|
||||||
|
BorderColor = Color.FromHex("#5A5A5A")
|
||||||
|
};
|
||||||
|
|
||||||
|
FooterPanel.PanelOverride = footerStyleBox;
|
||||||
|
MainPanel.PanelOverride = new StyleBoxFlat(Color.FromHex(PanelBgColor));
|
||||||
|
|
||||||
|
ButtonClear.AddStyleClass("ButtonColorRed");
|
||||||
|
ButtonLinkDefault.Disabled = true;
|
||||||
|
|
||||||
|
_links = new LinksRender(ButtonContainerLeft, ButtonContainerRight);
|
||||||
|
_links.VerticalExpand = true;
|
||||||
|
MiddleContainer.AddChild(_links);
|
||||||
|
|
||||||
|
ButtonOk.OnPressed += _ => Close();
|
||||||
|
ButtonLinkDefault.OnPressed += _ => LinkDefaults();
|
||||||
|
ButtonClear.OnPressed += _ => _userInterface.SendMessage(new NetworkConfiguratorClearLinksMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateState(DeviceLinkUserInterfaceState linkState)
|
||||||
|
{
|
||||||
|
ButtonContainerLeft.RemoveAllChildren();
|
||||||
|
ButtonContainerRight.RemoveAllChildren();
|
||||||
|
|
||||||
|
_sources.Clear();
|
||||||
|
_sources.AddRange(linkState.Sources);
|
||||||
|
_links.SourceButtons.Clear();
|
||||||
|
var i = 0;
|
||||||
|
foreach (var source in _sources)
|
||||||
|
{
|
||||||
|
var button = CreateButton(ButtonPosition.Left, source.Name, source.Description, source.ID, i);
|
||||||
|
ButtonContainerLeft.AddChild(button);
|
||||||
|
_links.SourceButtons.Add(source.ID, button);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
_sinks.Clear();
|
||||||
|
_sinks.AddRange(linkState.Sinks);
|
||||||
|
_links.SinkButtons.Clear();
|
||||||
|
i = 0;
|
||||||
|
foreach (var sink in _sinks)
|
||||||
|
{
|
||||||
|
var button = CreateButton(ButtonPosition.Right, sink.Name, sink.Description, sink.ID, i);
|
||||||
|
ButtonContainerRight.AddChild(button);
|
||||||
|
_links.SinkButtons.Add(sink.ID, button);
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
_links.Links.Clear();
|
||||||
|
_links.Links.AddRange(linkState.Links);
|
||||||
|
_defaults = linkState.Defaults;
|
||||||
|
|
||||||
|
ButtonLinkDefault.Disabled = _defaults == default;
|
||||||
|
FromAddressLabel.Text = linkState.SourceAddress;
|
||||||
|
ToAddressLabel.Text = linkState.SinkAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LinkDefaults()
|
||||||
|
{
|
||||||
|
if (_defaults == default)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_userInterface.SendMessage(new NetworkConfiguratorLinksSaveMessage(_defaults));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Button CreateButton(ButtonPosition position, string name, string description, string id, int index)
|
||||||
|
{
|
||||||
|
var button = new Button();
|
||||||
|
button.AddStyleClass("OpenBoth");
|
||||||
|
button.Text = Loc.GetString(name);
|
||||||
|
button.ToolTip = Loc.GetString(description);
|
||||||
|
button.ToggleMode = true;
|
||||||
|
button.OnPressed += args => OnButtonPressed(args, position, id, index);
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnButtonPressed(BaseButton.ButtonEventArgs args, ButtonPosition position, string id, int index)
|
||||||
|
{
|
||||||
|
var key = (position, id, index);
|
||||||
|
if (_selectedButton == key)
|
||||||
|
{
|
||||||
|
args.Button.Pressed = false;
|
||||||
|
_selectedButton = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_selectedButton.HasValue)
|
||||||
|
{
|
||||||
|
args.Button.Pressed = true;
|
||||||
|
_selectedButton = key;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_selectedButton.Value.position == position)
|
||||||
|
{
|
||||||
|
args.Button.Pressed = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var left = _selectedButton.Value.position == ButtonPosition.Left ? _selectedButton.Value.id : id;
|
||||||
|
var right = _selectedButton.Value.position == ButtonPosition.Left ? id : _selectedButton.Value.id;
|
||||||
|
|
||||||
|
_userInterface.SendMessage(new NetworkConfiguratorToggleLinkMessage(left, right));
|
||||||
|
|
||||||
|
args.Button.Pressed = false;
|
||||||
|
|
||||||
|
var container = _selectedButton.Value.position == ButtonPosition.Left ? ButtonContainerLeft : ButtonContainerRight;
|
||||||
|
if (container.GetChild(_selectedButton.Value.index) is Button button)
|
||||||
|
button.Pressed = false;
|
||||||
|
|
||||||
|
_selectedButton = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private enum ButtonPosition
|
||||||
|
{
|
||||||
|
Left,
|
||||||
|
Right
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Draws lines between linked ports using bezier curve calculated with polynomial coefficients
|
||||||
|
/// See: https://youtu.be/jvPPXbo87ds?t=351
|
||||||
|
/// </summary>
|
||||||
|
private sealed class LinksRender : Control
|
||||||
|
{
|
||||||
|
public readonly List<(string, string)> Links = new();
|
||||||
|
public readonly Dictionary<string, Button> SourceButtons = new();
|
||||||
|
public readonly Dictionary<string, Button> SinkButtons = new();
|
||||||
|
private readonly BoxContainer _leftButtonContainer;
|
||||||
|
private readonly BoxContainer _rightButtonContainer;
|
||||||
|
|
||||||
|
public LinksRender(BoxContainer leftButtonContainer, BoxContainer rightButtonContainer)
|
||||||
|
{
|
||||||
|
_leftButtonContainer = leftButtonContainer;
|
||||||
|
_rightButtonContainer = rightButtonContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Draw(DrawingHandleScreen handle)
|
||||||
|
{
|
||||||
|
foreach (var (left, right) in Links)
|
||||||
|
{
|
||||||
|
if (!SourceButtons.TryGetValue(left, out var leftChild) || !SinkButtons.TryGetValue(right, out var rightChild))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var leftOffset = _leftButtonContainer.PixelPosition.Y;
|
||||||
|
var rightOffset = _rightButtonContainer.PixelPosition.Y;
|
||||||
|
|
||||||
|
var y1 = leftChild.PixelPosition.Y + leftChild.PixelHeight / 2 + leftOffset;
|
||||||
|
var y2 = rightChild.PixelPosition.Y + rightChild.PixelHeight / 2 + rightOffset;
|
||||||
|
|
||||||
|
if (left == right)
|
||||||
|
{
|
||||||
|
handle.DrawLine((0, y1), (PixelWidth, y2), Color.Cyan);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var controls = new List<Vector2>
|
||||||
|
{
|
||||||
|
new(0, y1),
|
||||||
|
new(30, y1),
|
||||||
|
new(PixelWidth - 30, y2),
|
||||||
|
new(PixelWidth, y2),
|
||||||
|
};
|
||||||
|
|
||||||
|
//Calculate coefficients
|
||||||
|
var c0 = controls[0];
|
||||||
|
var c1 = controls[0] * -3 + controls[1] * 3;
|
||||||
|
var c2 = controls[0] * 3 + controls[1] * -6 + controls[2] * 3;
|
||||||
|
var c3 = controls[0] * -1 + controls[1] * 3 + controls[2] * -3 + controls[3];
|
||||||
|
|
||||||
|
var points = new List<Vector2>();
|
||||||
|
|
||||||
|
//Calculate points using coefficients
|
||||||
|
for (float t = 0; t <= 1; t += 0.0001f)
|
||||||
|
{
|
||||||
|
var point = c0 + c1 * t + c2 * (t * t) + c3 * (t * t * t);
|
||||||
|
points.Add(point);
|
||||||
|
}
|
||||||
|
|
||||||
|
handle.DrawPrimitives(DrawPrimitiveTopology.LineStrip, points.ToArray(), Color.Cyan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
|
using Content.Client.NetworkConfigurator.Systems;
|
||||||
using Content.Shared.DeviceNetwork;
|
using Content.Shared.DeviceNetwork;
|
||||||
|
using Content.Shared.DeviceNetwork.Components;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Shared.Enums;
|
using Robust.Shared.Enums;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||||
xmlns:networkConfigurator="clr-namespace:Content.Client.NetworkConfigurator"
|
xmlns:networkConfigurator="clr-namespace:Content.Client.NetworkConfigurator"
|
||||||
Title="Network Configurator" MinSize="220 400">
|
Title="{Loc 'network-configurator-title-saved-devices'}" MinSize="220 400">
|
||||||
<BoxContainer Orientation="Vertical" VerticalExpand="True">
|
<BoxContainer Orientation="Vertical" VerticalExpand="True">
|
||||||
<networkConfigurator:NetworkConfiguratorDeviceList Name="DeviceList" />
|
<networkConfigurator:NetworkConfiguratorDeviceList Name="DeviceList" />
|
||||||
<BoxContainer Orientation="Horizontal" Margin="8 8 8 8">
|
<BoxContainer Orientation="Horizontal" Margin="8 8 8 8">
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
using System.Linq;
|
|
||||||
using Content.Shared.DeviceNetwork;
|
using Content.Shared.DeviceNetwork;
|
||||||
using Robust.Client.Graphics;
|
|
||||||
|
|
||||||
namespace Content.Client.NetworkConfigurator;
|
namespace Content.Client.NetworkConfigurator.Systems;
|
||||||
|
|
||||||
public sealed class DeviceListSystem : SharedDeviceListSystem
|
public sealed class DeviceListSystem : SharedDeviceListSystem
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,15 +1,22 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Client.Actions;
|
using Content.Client.Actions;
|
||||||
using Content.Shared.Actions;
|
using Content.Client.Items;
|
||||||
|
using Content.Client.Message;
|
||||||
|
using Content.Client.Stylesheets;
|
||||||
using Content.Shared.Actions.ActionTypes;
|
using Content.Shared.Actions.ActionTypes;
|
||||||
using Content.Shared.DeviceNetwork;
|
using Content.Shared.DeviceNetwork.Components;
|
||||||
|
using Content.Shared.DeviceNetwork.Systems;
|
||||||
|
using Content.Shared.Input;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
|
using Robust.Client.Input;
|
||||||
using Robust.Client.Player;
|
using Robust.Client.Player;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Shared.Console;
|
using Robust.Shared.Console;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
namespace Content.Client.NetworkConfigurator;
|
namespace Content.Client.NetworkConfigurator.Systems;
|
||||||
|
|
||||||
public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||||
{
|
{
|
||||||
@@ -17,6 +24,7 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
|||||||
[Dependency] private readonly IOverlayManager _overlay = default!;
|
[Dependency] private readonly IOverlayManager _overlay = default!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
[Dependency] private readonly ActionsSystem _actions = default!;
|
[Dependency] private readonly ActionsSystem _actions = default!;
|
||||||
|
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||||
|
|
||||||
private const string Action = "ClearNetworkLinkOverlays";
|
private const string Action = "ClearNetworkLinkOverlays";
|
||||||
|
|
||||||
@@ -25,6 +33,13 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
|||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
SubscribeLocalEvent<ClearAllOverlaysEvent>(_ => ClearAllOverlays());
|
SubscribeLocalEvent<ClearAllOverlaysEvent>(_ => ClearAllOverlays());
|
||||||
|
SubscribeLocalEvent<NetworkConfiguratorComponent, ItemStatusCollectMessage>(OnCollectItemStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCollectItemStatus(EntityUid uid, NetworkConfiguratorComponent configurator, ItemStatusCollectMessage args)
|
||||||
|
{
|
||||||
|
_inputManager.TryGetKeyBinding((ContentKeyFunctions.AltUseItemInHand), out var binding);
|
||||||
|
args.Controls.Add(new StatusControl(configurator, binding?.GetKeyString() ?? ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool ConfiguredListIsTracked(EntityUid uid, NetworkConfiguratorComponent? component = null)
|
public bool ConfiguredListIsTracked(EntityUid uid, NetworkConfiguratorComponent? component = null)
|
||||||
@@ -102,6 +117,41 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
|||||||
|
|
||||||
component.ActiveDeviceList = list;
|
component.ActiveDeviceList = list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private sealed class StatusControl : Control
|
||||||
|
{
|
||||||
|
private readonly RichTextLabel _label;
|
||||||
|
private readonly NetworkConfiguratorComponent _configurator;
|
||||||
|
private readonly string _keyBindingName;
|
||||||
|
|
||||||
|
private bool? _linkModeActive = null;
|
||||||
|
|
||||||
|
public StatusControl(NetworkConfiguratorComponent configurator, string keyBindingName)
|
||||||
|
{
|
||||||
|
_configurator = configurator;
|
||||||
|
_keyBindingName = keyBindingName;
|
||||||
|
_label = new RichTextLabel { StyleClasses = { StyleNano.StyleClassItemStatus } };
|
||||||
|
AddChild(_label);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void FrameUpdate(FrameEventArgs args)
|
||||||
|
{
|
||||||
|
base.FrameUpdate(args);
|
||||||
|
|
||||||
|
if (_linkModeActive != null && _linkModeActive == _configurator.LinkModeActive)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_linkModeActive = _configurator.LinkModeActive;
|
||||||
|
|
||||||
|
var modeLocString = _linkModeActive??false
|
||||||
|
? "network-configurator-examine-mode-link"
|
||||||
|
: "network-configurator-examine-mode-list";
|
||||||
|
|
||||||
|
_label.SetMarkup(Loc.GetString("network-configurator-item-status-label",
|
||||||
|
("mode", Loc.GetString(modeLocString)),
|
||||||
|
("keybinding", _keyBindingName)));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ClearAllNetworkLinkOverlays : IConsoleCommand
|
public sealed class ClearAllNetworkLinkOverlays : IConsoleCommand
|
||||||
|
|||||||
@@ -82,7 +82,6 @@ namespace Content.IntegrationTests.Tests
|
|||||||
await server.WaitPost(() =>
|
await server.WaitPost(() =>
|
||||||
{
|
{
|
||||||
entityMan = IoCManager.Resolve<IEntityManager>();
|
entityMan = IoCManager.Resolve<IEntityManager>();
|
||||||
var mapManager = IoCManager.Resolve<IMapManager>();
|
|
||||||
|
|
||||||
var prototypeMan = IoCManager.Resolve<IPrototypeManager>();
|
var prototypeMan = IoCManager.Resolve<IPrototypeManager>();
|
||||||
var protoIds = prototypeMan
|
var protoIds = prototypeMan
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
using Content.Server.Atmos.Piping.Binary.Components;
|
using Content.Server.Atmos.Piping.Binary.Components;
|
||||||
using Content.Server.MachineLinking.Events;
|
using Content.Server.DeviceLinking.Events;
|
||||||
|
using Content.Server.DeviceLinking.Systems;
|
||||||
using Content.Server.MachineLinking.System;
|
using Content.Server.MachineLinking.System;
|
||||||
|
|
||||||
namespace Content.Server.Atmos.Piping.Binary.EntitySystems;
|
namespace Content.Server.Atmos.Piping.Binary.EntitySystems;
|
||||||
|
|
||||||
public sealed class SignalControlledValveSystem : EntitySystem
|
public sealed class SignalControlledValveSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly SignalLinkerSystem _signal = default!;
|
[Dependency] private readonly DeviceLinkSystem _signal = default!;
|
||||||
[Dependency] private readonly GasValveSystem _valve = default!;
|
[Dependency] private readonly GasValveSystem _valve = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -19,10 +20,10 @@ public sealed class SignalControlledValveSystem : EntitySystem
|
|||||||
|
|
||||||
private void OnInit(EntityUid uid, SignalControlledValveComponent comp, ComponentInit args)
|
private void OnInit(EntityUid uid, SignalControlledValveComponent comp, ComponentInit args)
|
||||||
{
|
{
|
||||||
_signal.EnsureReceiverPorts(uid, comp.OpenPort, comp.ClosePort, comp.TogglePort);
|
_signal.EnsureSinkPorts(uid, comp.OpenPort, comp.ClosePort, comp.TogglePort);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSignalReceived(EntityUid uid, SignalControlledValveComponent comp, SignalReceivedEvent args)
|
private void OnSignalReceived(EntityUid uid, SignalControlledValveComponent comp, ref SignalReceivedEvent args)
|
||||||
{
|
{
|
||||||
if (!TryComp<GasValveComponent>(uid, out var valve))
|
if (!TryComp<GasValveComponent>(uid, out var valve))
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
using Content.Server.Atmos.EntitySystems;
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Server.Atmos.Monitor.Components;
|
|
||||||
using Content.Server.Atmos.Monitor.Systems;
|
using Content.Server.Atmos.Monitor.Systems;
|
||||||
using Content.Server.Atmos.Piping.Components;
|
using Content.Server.Atmos.Piping.Components;
|
||||||
using Content.Server.Atmos.Piping.Unary.Components;
|
using Content.Server.Atmos.Piping.Unary.Components;
|
||||||
|
using Content.Server.DeviceLinking.Events;
|
||||||
|
using Content.Server.DeviceLinking.Systems;
|
||||||
using Content.Server.DeviceNetwork;
|
using Content.Server.DeviceNetwork;
|
||||||
using Content.Server.DeviceNetwork.Components;
|
using Content.Server.DeviceNetwork.Components;
|
||||||
using Content.Server.DeviceNetwork.Systems;
|
using Content.Server.DeviceNetwork.Systems;
|
||||||
using Content.Server.MachineLinking.Events;
|
|
||||||
using Content.Server.MachineLinking.System;
|
|
||||||
using Content.Server.NodeContainer;
|
using Content.Server.NodeContainer;
|
||||||
using Content.Server.NodeContainer.Nodes;
|
using Content.Server.NodeContainer.Nodes;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
@@ -28,7 +27,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||||
[Dependency] private readonly DeviceNetworkSystem _deviceNetSystem = default!;
|
[Dependency] private readonly DeviceNetworkSystem _deviceNetSystem = default!;
|
||||||
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
|
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
[Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default!;
|
[Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = default!;
|
||||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||||
@@ -224,10 +223,10 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
|||||||
private void OnInit(EntityUid uid, GasVentPumpComponent component, ComponentInit args)
|
private void OnInit(EntityUid uid, GasVentPumpComponent component, ComponentInit args)
|
||||||
{
|
{
|
||||||
if (component.CanLink)
|
if (component.CanLink)
|
||||||
_signalSystem.EnsureReceiverPorts(uid, component.PressurizePort, component.DepressurizePort);
|
_signalSystem.EnsureSinkPorts(uid, component.PressurizePort, component.DepressurizePort);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSignalReceived(EntityUid uid, GasVentPumpComponent component, SignalReceivedEvent args)
|
private void OnSignalReceived(EntityUid uid, GasVentPumpComponent component, ref SignalReceivedEvent args)
|
||||||
{
|
{
|
||||||
if (!component.CanLink)
|
if (!component.CanLink)
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ using System.Diagnostics.CodeAnalysis;
|
|||||||
using Content.Server.Access.Systems;
|
using Content.Server.Access.Systems;
|
||||||
using Content.Server.Cargo.Components;
|
using Content.Server.Cargo.Components;
|
||||||
using Content.Server.Labels.Components;
|
using Content.Server.Labels.Components;
|
||||||
using Content.Server.MachineLinking.System;
|
using Content.Server.DeviceLinking.Systems;
|
||||||
using Content.Server.Popups;
|
using Content.Server.Popups;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
using Content.Shared.Access.Systems;
|
using Content.Shared.Access.Systems;
|
||||||
@@ -34,7 +34,7 @@ namespace Content.Server.Cargo.Systems
|
|||||||
|
|
||||||
[Dependency] private readonly IdCardSystem _idCardSystem = default!;
|
[Dependency] private readonly IdCardSystem _idCardSystem = default!;
|
||||||
[Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!;
|
[Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!;
|
||||||
[Dependency] private readonly SignalLinkerSystem _linker = default!;
|
[Dependency] private readonly DeviceLinkSystem _linker = default!;
|
||||||
[Dependency] private readonly PopupSystem _popup = default!;
|
[Dependency] private readonly PopupSystem _popup = default!;
|
||||||
[Dependency] private readonly StationSystem _station = default!;
|
[Dependency] private readonly StationSystem _station = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ public sealed partial class CargoSystem
|
|||||||
|
|
||||||
private void OnInit(EntityUid uid, CargoTelepadComponent telepad, ComponentInit args)
|
private void OnInit(EntityUid uid, CargoTelepadComponent telepad, ComponentInit args)
|
||||||
{
|
{
|
||||||
_linker.EnsureReceiverPorts(uid, telepad.ReceiverPort);
|
_linker.EnsureSinkPorts(uid, telepad.ReceiverPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetEnabled(CargoTelepadComponent component, ApcPowerReceiverComponent? receiver = null,
|
private void SetEnabled(CargoTelepadComponent component, ApcPowerReceiverComponent? receiver = null,
|
||||||
|
|||||||
@@ -4,11 +4,10 @@ using Robust.Shared.Timing;
|
|||||||
using Content.Server.Administration.Logs;
|
using Content.Server.Administration.Logs;
|
||||||
using Content.Server.Medical.Components;
|
using Content.Server.Medical.Components;
|
||||||
using Content.Server.Cloning.Components;
|
using Content.Server.Cloning.Components;
|
||||||
using Content.Server.MachineLinking.Components;
|
using Content.Server.DeviceLinking.Events;
|
||||||
|
using Content.Server.DeviceLinking.Systems;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Server.Mind.Components;
|
using Content.Server.Mind.Components;
|
||||||
using Content.Server.MachineLinking.System;
|
|
||||||
using Content.Server.MachineLinking.Events;
|
|
||||||
using Content.Server.UserInterface;
|
using Content.Server.UserInterface;
|
||||||
using Content.Server.Power.EntitySystems;
|
using Content.Server.Power.EntitySystems;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
@@ -16,7 +15,8 @@ using Robust.Server.Player;
|
|||||||
using Content.Shared.Cloning.CloningConsole;
|
using Content.Shared.Cloning.CloningConsole;
|
||||||
using Content.Shared.Cloning;
|
using Content.Shared.Cloning;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
using Content.Shared.MachineLinking.Events;
|
using Content.Shared.DeviceLinking;
|
||||||
|
using Content.Shared.DeviceLinking.Events;
|
||||||
using Content.Shared.IdentityManagement;
|
using Content.Shared.IdentityManagement;
|
||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
@@ -26,7 +26,7 @@ namespace Content.Server.Cloning
|
|||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public sealed class CloningConsoleSystem : EntitySystem
|
public sealed class CloningConsoleSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
|
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
||||||
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
[Dependency] private readonly IAdminLogManager _adminLogger = default!;
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
[Dependency] private readonly IPlayerManager _playerManager = default!;
|
||||||
[Dependency] private readonly CloningSystem _cloningSystem = default!;
|
[Dependency] private readonly CloningSystem _cloningSystem = default!;
|
||||||
@@ -48,7 +48,7 @@ namespace Content.Server.Cloning
|
|||||||
|
|
||||||
private void OnInit(EntityUid uid, CloningConsoleComponent component, ComponentInit args)
|
private void OnInit(EntityUid uid, CloningConsoleComponent component, ComponentInit args)
|
||||||
{
|
{
|
||||||
_signalSystem.EnsureTransmitterPorts(uid, CloningConsoleComponent.ScannerPort, CloningConsoleComponent.PodPort);
|
_signalSystem.EnsureSourcePorts(uid, CloningConsoleComponent.ScannerPort, CloningConsoleComponent.PodPort);
|
||||||
}
|
}
|
||||||
private void OnButtonPressed(EntityUid uid, CloningConsoleComponent consoleComponent, UiButtonPressedMessage args)
|
private void OnButtonPressed(EntityUid uid, CloningConsoleComponent consoleComponent, UiButtonPressedMessage args)
|
||||||
{
|
{
|
||||||
@@ -72,20 +72,20 @@ namespace Content.Server.Cloning
|
|||||||
|
|
||||||
private void OnMapInit(EntityUid uid, CloningConsoleComponent component, MapInitEvent args)
|
private void OnMapInit(EntityUid uid, CloningConsoleComponent component, MapInitEvent args)
|
||||||
{
|
{
|
||||||
if (!TryComp<SignalTransmitterComponent>(uid, out var receiver))
|
if (!TryComp<DeviceLinkSourceComponent>(uid, out var receiver))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var port in receiver.Outputs.Values.SelectMany(ports => ports))
|
foreach (var port in receiver.Outputs.Values.SelectMany(ports => ports))
|
||||||
{
|
{
|
||||||
if (TryComp<MedicalScannerComponent>(port.Uid, out var scanner))
|
if (TryComp<MedicalScannerComponent>(port, out var scanner))
|
||||||
{
|
{
|
||||||
component.GeneticScanner = port.Uid;
|
component.GeneticScanner = port;
|
||||||
scanner.ConnectedConsole = uid;
|
scanner.ConnectedConsole = uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryComp<CloningPodComponent>(port.Uid, out var pod))
|
if (TryComp<CloningPodComponent>(port, out var pod))
|
||||||
{
|
{
|
||||||
component.CloningPod = port.Uid;
|
component.CloningPod = port;
|
||||||
pod.ConnectedConsole = uid;
|
pod.ConnectedConsole = uid;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -93,15 +93,15 @@ namespace Content.Server.Cloning
|
|||||||
|
|
||||||
private void OnNewLink(EntityUid uid, CloningConsoleComponent component, NewLinkEvent args)
|
private void OnNewLink(EntityUid uid, CloningConsoleComponent component, NewLinkEvent args)
|
||||||
{
|
{
|
||||||
if (TryComp<MedicalScannerComponent>(args.Receiver, out var scanner) && args.TransmitterPort == CloningConsoleComponent.ScannerPort)
|
if (TryComp<MedicalScannerComponent>(args.Sink, out var scanner) && args.SourcePort == CloningConsoleComponent.ScannerPort)
|
||||||
{
|
{
|
||||||
component.GeneticScanner = args.Receiver;
|
component.GeneticScanner = args.Sink;
|
||||||
scanner.ConnectedConsole = uid;
|
scanner.ConnectedConsole = uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryComp<CloningPodComponent>(args.Receiver, out var pod) && args.TransmitterPort == CloningConsoleComponent.PodPort)
|
if (TryComp<CloningPodComponent>(args.Sink, out var pod) && args.SourcePort == CloningConsoleComponent.PodPort)
|
||||||
{
|
{
|
||||||
component.CloningPod = args.Receiver;
|
component.CloningPod = args.Sink;
|
||||||
pod.ConnectedConsole = uid;
|
pod.ConnectedConsole = uid;
|
||||||
}
|
}
|
||||||
RecheckConnections(uid, component.CloningPod, component.GeneticScanner, component);
|
RecheckConnections(uid, component.CloningPod, component.GeneticScanner, component);
|
||||||
|
|||||||
@@ -10,15 +10,15 @@ using Content.Server.Power.EntitySystems;
|
|||||||
using Content.Server.Atmos.EntitySystems;
|
using Content.Server.Atmos.EntitySystems;
|
||||||
using Content.Server.EUI;
|
using Content.Server.EUI;
|
||||||
using Content.Server.Humanoid;
|
using Content.Server.Humanoid;
|
||||||
using Content.Server.MachineLinking.System;
|
|
||||||
using Content.Server.MachineLinking.Events;
|
|
||||||
using Content.Shared.Chemistry.Components;
|
using Content.Shared.Chemistry.Components;
|
||||||
using Content.Server.Fluids.EntitySystems;
|
using Content.Server.Fluids.EntitySystems;
|
||||||
using Content.Server.Chat.Systems;
|
using Content.Server.Chat.Systems;
|
||||||
using Content.Server.Construction;
|
using Content.Server.Construction;
|
||||||
|
using Content.Server.DeviceLinking.Events;
|
||||||
|
using Content.Server.DeviceLinking.Systems;
|
||||||
using Content.Server.Materials;
|
using Content.Server.Materials;
|
||||||
using Content.Server.Stack;
|
|
||||||
using Content.Server.Jobs;
|
using Content.Server.Jobs;
|
||||||
|
using Content.Shared.DeviceLinking.Events;
|
||||||
using Content.Shared.Emag.Components;
|
using Content.Shared.Emag.Components;
|
||||||
using Content.Shared.Humanoid;
|
using Content.Shared.Humanoid;
|
||||||
using Content.Shared.Humanoid.Prototypes;
|
using Content.Shared.Humanoid.Prototypes;
|
||||||
@@ -43,7 +43,7 @@ namespace Content.Server.Cloning
|
|||||||
{
|
{
|
||||||
public sealed class CloningSystem : EntitySystem
|
public sealed class CloningSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
|
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
||||||
[Dependency] private readonly IPlayerManager _playerManager = null!;
|
[Dependency] private readonly IPlayerManager _playerManager = null!;
|
||||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||||
[Dependency] private readonly EuiManager _euiManager = null!;
|
[Dependency] private readonly EuiManager _euiManager = null!;
|
||||||
@@ -84,7 +84,7 @@ namespace Content.Server.Cloning
|
|||||||
private void OnComponentInit(EntityUid uid, CloningPodComponent clonePod, ComponentInit args)
|
private void OnComponentInit(EntityUid uid, CloningPodComponent clonePod, ComponentInit args)
|
||||||
{
|
{
|
||||||
clonePod.BodyContainer = _containerSystem.EnsureContainer<ContainerSlot>(clonePod.Owner, "clonepod-bodyContainer");
|
clonePod.BodyContainer = _containerSystem.EnsureContainer<ContainerSlot>(clonePod.Owner, "clonepod-bodyContainer");
|
||||||
_signalSystem.EnsureReceiverPorts(uid, CloningPodComponent.PodPort);
|
_signalSystem.EnsureSinkPorts(uid, CloningPodComponent.PodPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPartsRefreshed(EntityUid uid, CloningPodComponent component, RefreshPartsEvent args)
|
private void OnPartsRefreshed(EntityUid uid, CloningPodComponent component, RefreshPartsEvent args)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Content.Server.MachineLinking.Components;
|
namespace Content.Server.DeviceLinking.Components;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is used for automatic linkage with buttons and other transmitters.
|
/// This is used for automatic linkage with buttons and other transmitters.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Content.Server.MachineLinking.Components;
|
namespace Content.Server.DeviceLinking.Components;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This is used for automatic linkage with various receivers, like shutters.
|
/// This is used for automatic linkage with various receivers, like shutters.
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using Content.Shared.MachineLinking;
|
using Content.Shared.MachineLinking;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
namespace Content.Server.MachineLinking.Components
|
namespace Content.Server.DeviceLinking.Components
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed class DoorSignalControlComponent : Component
|
public sealed class DoorSignalControlComponent : Component
|
||||||
@@ -2,7 +2,7 @@ using Content.Shared.MachineLinking;
|
|||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
namespace Content.Server.MachineLinking.Components
|
namespace Content.Server.DeviceLinking.Components
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Simple switch that will fire ports when toggled on or off. A button is jsut a switch that signals on the
|
/// Simple switch that will fire ports when toggled on or off. A button is jsut a switch that signals on the
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using Content.Shared.MachineLinking;
|
using Content.Shared.MachineLinking;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
namespace Content.Server.MachineLinking.Components
|
namespace Content.Server.DeviceLinking.Components
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends out a signal to machine linked objects.
|
/// Sends out a signal to machine linked objects.
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
|
using Content.Shared.DeviceLinking;
|
||||||
using Content.Shared.MachineLinking;
|
using Content.Shared.MachineLinking;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
namespace Content.Server.MachineLinking.Components
|
namespace Content.Server.DeviceLinking.Components
|
||||||
{
|
{
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed class TwoWayLeverComponent : Component
|
public sealed class TwoWayLeverComponent : Component
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
using Content.Server.DeviceNetwork;
|
||||||
|
|
||||||
|
namespace Content.Server.DeviceLinking.Events;
|
||||||
|
|
||||||
|
[ByRefEvent]
|
||||||
|
public readonly record struct SignalReceivedEvent(string Port, EntityUid? Trigger = null, NetworkPayload? Data = null);
|
||||||
@@ -1,13 +1,14 @@
|
|||||||
using Content.Server.MachineLinking.Components;
|
using Content.Server.DeviceLinking.Components;
|
||||||
|
using Content.Server.MachineLinking.System;
|
||||||
|
|
||||||
namespace Content.Server.MachineLinking.System;
|
namespace Content.Server.DeviceLinking.Systems;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// This handles automatically linking autolinked entities at round-start.
|
/// This handles automatically linking autolinked entities at round-start.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class AutoLinkSystem : EntitySystem
|
public sealed class AutoLinkSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly SignalLinkerSystem _signalLinkerSystem = default!;
|
[Dependency] private readonly DeviceLinkSystem _deviceLinkSystem = default!;
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -29,7 +30,7 @@ public sealed class AutoLinkSystem : EntitySystem
|
|||||||
if (rxXform.GridUid != xform.GridUid)
|
if (rxXform.GridUid != xform.GridUid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
_signalLinkerSystem.TryLinkDefaults(receiver.Owner, uid, null);
|
_deviceLinkSystem.LinkDefaults(null, uid, receiver.Owner);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
114
Content.Server/DeviceLinking/Systems/DeviceLinkSystem.cs
Normal file
114
Content.Server/DeviceLinking/Systems/DeviceLinkSystem.cs
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
using Content.Server.DeviceLinking.Events;
|
||||||
|
using Content.Server.DeviceNetwork;
|
||||||
|
using Content.Server.DeviceNetwork.Components;
|
||||||
|
using Content.Server.DeviceNetwork.Systems;
|
||||||
|
using Content.Server.MachineLinking.Components;
|
||||||
|
using Content.Shared.DeviceLinking;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Server.DeviceLinking.Systems;
|
||||||
|
|
||||||
|
public sealed class DeviceLinkSystem : SharedDeviceLinkSystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly DeviceNetworkSystem _deviceNetworkSystem = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<SignalTransmitterComponent, MapInitEvent>(OnTransmitterStartup);
|
||||||
|
SubscribeLocalEvent<DeviceLinkSinkComponent, DeviceNetworkPacketEvent>(OnPacketReceived);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Moves existing links from machine linking to device linking to ensure linked things still work even when the map wasn't updated yet
|
||||||
|
/// </summary>
|
||||||
|
private void OnTransmitterStartup(EntityUid sourceUid, SignalTransmitterComponent transmitterComponent, MapInitEvent args)
|
||||||
|
{
|
||||||
|
if (!TryComp<DeviceLinkSourceComponent?>(sourceUid, out var sourceComponent))
|
||||||
|
return;
|
||||||
|
|
||||||
|
Dictionary<EntityUid, List<(string, string)>> outputs = new();
|
||||||
|
foreach (var (transmitterPort, receiverPorts) in transmitterComponent.Outputs)
|
||||||
|
{
|
||||||
|
|
||||||
|
foreach (var receiverPort in receiverPorts)
|
||||||
|
{
|
||||||
|
outputs.GetOrNew(receiverPort.Uid).Add((transmitterPort, receiverPort.Port));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var (sinkUid, links) in outputs)
|
||||||
|
{
|
||||||
|
SaveLinks(null, sourceUid, sinkUid, links, sourceComponent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Sending & Receiving
|
||||||
|
/// <summary>
|
||||||
|
/// Sends a network payload directed at the sink entity.
|
||||||
|
/// Just raises a <see cref="SignalReceivedEvent"/> without data if the source or the sink doesn't have a <see cref="DeviceNetworkComponent"/>
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="uid">The source uid that invokes the port</param>
|
||||||
|
/// <param name="port">The port to invoke</param>
|
||||||
|
/// <param name="data">Optional data to send along</param>
|
||||||
|
/// <param name="sourceComponent"></param>
|
||||||
|
public void InvokePort(EntityUid uid, string port, NetworkPayload? data = null, DeviceLinkSourceComponent? sourceComponent = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref sourceComponent) || !sourceComponent.Outputs.TryGetValue(port, out var sinks))
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var sinkUid in sinks)
|
||||||
|
{
|
||||||
|
if (!sourceComponent.LinkedPorts.TryGetValue(sinkUid, out var links))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
foreach (var (source, sink) in links)
|
||||||
|
{
|
||||||
|
if (source != port)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
//Just skip using device networking if the source or the sink doesn't support it
|
||||||
|
if (!HasComp<DeviceNetworkComponent>(uid) || !TryComp<DeviceNetworkComponent?>(sinkUid, out var sinkNetworkComponent))
|
||||||
|
{
|
||||||
|
var eventArgs = new SignalReceivedEvent(sink, uid);
|
||||||
|
|
||||||
|
RaiseLocalEvent(sinkUid, ref eventArgs);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var payload = new NetworkPayload()
|
||||||
|
{
|
||||||
|
[InvokedPort] = sink
|
||||||
|
};
|
||||||
|
|
||||||
|
if (data != null)
|
||||||
|
{
|
||||||
|
//Prevent overriding the invoked port
|
||||||
|
data.Remove(InvokedPort);
|
||||||
|
foreach (var (key, value) in data)
|
||||||
|
{
|
||||||
|
payload.Add(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_deviceNetworkSystem.QueuePacket(uid, sinkNetworkComponent.Address, payload, sinkNetworkComponent.ReceiveFrequency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the payload has a port defined and if the port is present on the sink.
|
||||||
|
/// Raises a <see cref="SignalReceivedEvent"/> containing the payload when the check passes
|
||||||
|
/// </summary>
|
||||||
|
private void OnPacketReceived(EntityUid uid, DeviceLinkSinkComponent component, DeviceNetworkPacketEvent args)
|
||||||
|
{
|
||||||
|
if (!args.Data.TryGetValue(InvokedPort, out string? port) || !(component.Ports?.Contains(port) ?? false))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var eventArgs = new SignalReceivedEvent(port, args.Sender, args.Data);
|
||||||
|
RaiseLocalEvent(uid, ref eventArgs);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -1,16 +1,17 @@
|
|||||||
using Content.Server.MachineLinking.Components;
|
using Content.Server.DeviceLinking.Components;
|
||||||
using Content.Server.MachineLinking.Events;
|
using Content.Server.DeviceLinking.Events;
|
||||||
using Content.Server.Doors.Systems;
|
using Content.Server.Doors.Systems;
|
||||||
|
using Content.Server.MachineLinking.System;
|
||||||
using Content.Shared.Doors.Components;
|
using Content.Shared.Doors.Components;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
|
||||||
namespace Content.Server.MachineLinking.System
|
namespace Content.Server.DeviceLinking.Systems
|
||||||
{
|
{
|
||||||
[UsedImplicitly]
|
[UsedImplicitly]
|
||||||
public sealed class DoorSignalControlSystem : EntitySystem
|
public sealed class DoorSignalControlSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly DoorSystem _doorSystem = default!;
|
[Dependency] private readonly DoorSystem _doorSystem = default!;
|
||||||
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
|
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -18,13 +19,13 @@ namespace Content.Server.MachineLinking.System
|
|||||||
SubscribeLocalEvent<DoorSignalControlComponent, ComponentInit>(OnInit);
|
SubscribeLocalEvent<DoorSignalControlComponent, ComponentInit>(OnInit);
|
||||||
SubscribeLocalEvent<DoorSignalControlComponent, SignalReceivedEvent>(OnSignalReceived);
|
SubscribeLocalEvent<DoorSignalControlComponent, SignalReceivedEvent>(OnSignalReceived);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInit(EntityUid uid, DoorSignalControlComponent component, ComponentInit args)
|
private void OnInit(EntityUid uid, DoorSignalControlComponent component, ComponentInit args)
|
||||||
{
|
{
|
||||||
_signalSystem.EnsureReceiverPorts(uid, component.OpenPort, component.ClosePort, component.TogglePort);
|
_signalSystem.EnsureSinkPorts(uid, component.OpenPort, component.ClosePort, component.TogglePort);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSignalReceived(EntityUid uid, DoorSignalControlComponent component, SignalReceivedEvent args)
|
private void OnSignalReceived(EntityUid uid, DoorSignalControlComponent component, ref SignalReceivedEvent args)
|
||||||
{
|
{
|
||||||
if (!TryComp(uid, out DoorComponent? door))
|
if (!TryComp(uid, out DoorComponent? door))
|
||||||
return;
|
return;
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
using Content.Server.MachineLinking.Components;
|
using Content.Server.DeviceLinking.Components;
|
||||||
|
using Content.Server.MachineLinking.System;
|
||||||
using Content.Shared.Audio;
|
using Content.Shared.Audio;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Player;
|
||||||
|
|
||||||
namespace Content.Server.MachineLinking.System
|
namespace Content.Server.DeviceLinking.Systems
|
||||||
{
|
{
|
||||||
public sealed class SignalSwitchSystem : EntitySystem
|
public sealed class SignalSwitchSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
|
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -20,7 +21,7 @@ namespace Content.Server.MachineLinking.System
|
|||||||
|
|
||||||
private void OnInit(EntityUid uid, SignalSwitchComponent component, ComponentInit args)
|
private void OnInit(EntityUid uid, SignalSwitchComponent component, ComponentInit args)
|
||||||
{
|
{
|
||||||
_signalSystem.EnsureTransmitterPorts(uid, component.OnPort, component.OffPort);
|
_signalSystem.EnsureSourcePorts(uid, component.OnPort, component.OffPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnActivated(EntityUid uid, SignalSwitchComponent component, ActivateInWorldEvent args)
|
private void OnActivated(EntityUid uid, SignalSwitchComponent component, ActivateInWorldEvent args)
|
||||||
@@ -1,13 +1,13 @@
|
|||||||
|
using Content.Server.DeviceLinking.Components;
|
||||||
using Content.Server.Explosion.EntitySystems;
|
using Content.Server.Explosion.EntitySystems;
|
||||||
using Content.Server.MachineLinking.Components;
|
|
||||||
using Content.Shared.Interaction.Events;
|
using Content.Shared.Interaction.Events;
|
||||||
using Content.Shared.Timing;
|
using Content.Shared.Timing;
|
||||||
|
|
||||||
namespace Content.Server.MachineLinking.System;
|
namespace Content.Server.DeviceLinking.Systems;
|
||||||
|
|
||||||
public sealed class SignallerSystem : EntitySystem
|
public sealed class SignallerSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly SignalLinkerSystem _signal = default!;
|
[Dependency] private readonly DeviceLinkSystem _link = default!;
|
||||||
[Dependency] private readonly UseDelaySystem _useDelay = default!;
|
[Dependency] private readonly UseDelaySystem _useDelay = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -21,14 +21,14 @@ public sealed class SignallerSystem : EntitySystem
|
|||||||
|
|
||||||
private void OnInit(EntityUid uid, SignallerComponent component, ComponentInit args)
|
private void OnInit(EntityUid uid, SignallerComponent component, ComponentInit args)
|
||||||
{
|
{
|
||||||
_signal.EnsureTransmitterPorts(uid, component.Port);
|
_link.EnsureSourcePorts(uid, component.Port);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnUseInHand(EntityUid uid, SignallerComponent component, UseInHandEvent args)
|
private void OnUseInHand(EntityUid uid, SignallerComponent component, UseInHandEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled)
|
if (args.Handled)
|
||||||
return;
|
return;
|
||||||
_signal.InvokePort(uid, component.Port);
|
_link.InvokePort(uid, component.Port);
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,7 +43,7 @@ public sealed class SignallerSystem : EntitySystem
|
|||||||
if (hasUseDelay)
|
if (hasUseDelay)
|
||||||
_useDelay.BeginDelay(uid, useDelay);
|
_useDelay.BeginDelay(uid, useDelay);
|
||||||
|
|
||||||
_signal.InvokePort(uid, component.Port);
|
_link.InvokePort(uid, component.Port);
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
using Content.Server.MachineLinking.Components;
|
using Content.Server.DeviceLinking.Components;
|
||||||
|
using Content.Shared.DeviceLinking;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.MachineLinking;
|
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
using Robust.Server.GameObjects;
|
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.MachineLinking.System
|
namespace Content.Server.DeviceLinking.Systems
|
||||||
{
|
{
|
||||||
public sealed class TwoWayLeverSystem : EntitySystem
|
public sealed class TwoWayLeverSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
|
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
||||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||||
|
|
||||||
const string _leftToggleImage = "rotate_ccw.svg.192dpi.png";
|
const string _leftToggleImage = "rotate_ccw.svg.192dpi.png";
|
||||||
@@ -25,7 +24,7 @@ namespace Content.Server.MachineLinking.System
|
|||||||
|
|
||||||
private void OnInit(EntityUid uid, TwoWayLeverComponent component, ComponentInit args)
|
private void OnInit(EntityUid uid, TwoWayLeverComponent component, ComponentInit args)
|
||||||
{
|
{
|
||||||
_signalSystem.EnsureTransmitterPorts(uid, component.LeftPort, component.RightPort, component.MiddlePort);
|
_signalSystem.EnsureSourcePorts(uid, component.LeftPort, component.RightPort, component.MiddlePort);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnActivated(EntityUid uid, TwoWayLeverComponent component, ActivateInWorldEvent args)
|
private void OnActivated(EntityUid uid, TwoWayLeverComponent component, ActivateInWorldEvent args)
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.DeviceNetwork.Components;
|
using Content.Server.DeviceNetwork.Components;
|
||||||
using Content.Shared.DeviceNetwork;
|
using Content.Shared.DeviceNetwork;
|
||||||
|
using Content.Shared.DeviceNetwork.Components;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Server.DeviceLinking.Systems;
|
||||||
using Content.Server.DeviceNetwork.Components;
|
using Content.Server.DeviceNetwork.Components;
|
||||||
|
using Content.Server.UserInterface;
|
||||||
using Content.Shared.Access.Components;
|
using Content.Shared.Access.Components;
|
||||||
using Content.Shared.Access.Systems;
|
using Content.Shared.Access.Systems;
|
||||||
using Content.Shared.Database;
|
using Content.Shared.Database;
|
||||||
|
using Content.Shared.DeviceLinking;
|
||||||
using Content.Shared.DeviceNetwork;
|
using Content.Shared.DeviceNetwork;
|
||||||
|
using Content.Shared.DeviceNetwork.Components;
|
||||||
|
using Content.Shared.DeviceNetwork.Systems;
|
||||||
|
using Content.Shared.Examine;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Player;
|
using Robust.Shared.Timing;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Server.DeviceNetwork.Systems;
|
namespace Content.Server.DeviceNetwork.Systems;
|
||||||
@@ -19,11 +25,14 @@ namespace Content.Server.DeviceNetwork.Systems;
|
|||||||
public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly DeviceListSystem _deviceListSystem = default!;
|
[Dependency] private readonly DeviceListSystem _deviceListSystem = default!;
|
||||||
|
[Dependency] private readonly DeviceLinkSystem _deviceLinkSystem = default!;
|
||||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||||
[Dependency] private readonly AccessReaderSystem _accessSystem = default!;
|
[Dependency] private readonly AccessReaderSystem _accessSystem = default!;
|
||||||
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
[Dependency] private readonly SharedInteractionSystem _interactionSystem = default!;
|
||||||
|
[Dependency] private readonly AudioSystem _audioSystem = default!;
|
||||||
|
[Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!;
|
||||||
|
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
@@ -32,17 +41,23 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
|||||||
SubscribeLocalEvent<NetworkConfiguratorComponent, MapInitEvent>(OnMapInit);
|
SubscribeLocalEvent<NetworkConfiguratorComponent, MapInitEvent>(OnMapInit);
|
||||||
|
|
||||||
//Interaction
|
//Interaction
|
||||||
SubscribeLocalEvent<NetworkConfiguratorComponent, AfterInteractEvent>((uid, component, args) => OnUsed(uid, component, args.Target, args.User, args.CanReach)); //TODO: Replace with utility verb?
|
SubscribeLocalEvent<NetworkConfiguratorComponent, AfterInteractEvent>(AfterInteract); //TODO: Replace with utility verb?
|
||||||
|
SubscribeLocalEvent<NetworkConfiguratorComponent, ExaminedEvent>(DoExamine);
|
||||||
|
|
||||||
//Verbs
|
//Verbs
|
||||||
SubscribeLocalEvent<NetworkConfiguratorComponent, GetVerbsEvent<UtilityVerb>>(OnAddInteractVerb);
|
SubscribeLocalEvent<NetworkConfiguratorComponent, GetVerbsEvent<UtilityVerb>>(OnAddInteractVerb);
|
||||||
SubscribeLocalEvent<DeviceNetworkComponent, GetVerbsEvent<AlternativeVerb>>(OnAddAlternativeSaveDeviceVerb);
|
SubscribeLocalEvent<DeviceNetworkComponent, GetVerbsEvent<AlternativeVerb>>(OnAddAlternativeSaveDeviceVerb);
|
||||||
|
SubscribeLocalEvent<NetworkConfiguratorComponent, GetVerbsEvent<AlternativeVerb>>(OnAddSwitchModeVerb);
|
||||||
|
|
||||||
//UI
|
//UI
|
||||||
SubscribeLocalEvent<NetworkConfiguratorComponent, BoundUIClosedEvent>(OnUiClosed);
|
SubscribeLocalEvent<NetworkConfiguratorComponent, BoundUIClosedEvent>(OnUiClosed);
|
||||||
SubscribeLocalEvent<NetworkConfiguratorComponent, NetworkConfiguratorRemoveDeviceMessage>(OnRemoveDevice);
|
SubscribeLocalEvent<NetworkConfiguratorComponent, NetworkConfiguratorRemoveDeviceMessage>(OnRemoveDevice);
|
||||||
SubscribeLocalEvent<NetworkConfiguratorComponent, NetworkConfiguratorClearDevicesMessage>(OnClearDevice);
|
SubscribeLocalEvent<NetworkConfiguratorComponent, NetworkConfiguratorClearDevicesMessage>(OnClearDevice);
|
||||||
|
SubscribeLocalEvent<NetworkConfiguratorComponent, NetworkConfiguratorLinksSaveMessage>(OnSaveLinks);
|
||||||
|
SubscribeLocalEvent<NetworkConfiguratorComponent, NetworkConfiguratorClearLinksMessage>(OnClearLinks);
|
||||||
|
SubscribeLocalEvent<NetworkConfiguratorComponent, NetworkConfiguratorToggleLinkMessage>(OnToggleLinks);
|
||||||
SubscribeLocalEvent<NetworkConfiguratorComponent, NetworkConfiguratorButtonPressedMessage>(OnConfigButtonPressed);
|
SubscribeLocalEvent<NetworkConfiguratorComponent, NetworkConfiguratorButtonPressedMessage>(OnConfigButtonPressed);
|
||||||
|
SubscribeLocalEvent<NetworkConfiguratorComponent, ActivatableUIOpenAttemptEvent>(OnUiOpenAttempt);
|
||||||
|
|
||||||
SubscribeLocalEvent<DeviceListComponent, ComponentRemove>(OnComponentRemoved);
|
SubscribeLocalEvent<DeviceListComponent, ComponentRemove>(OnComponentRemoved);
|
||||||
}
|
}
|
||||||
@@ -62,14 +77,14 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
//The network configurator is a handheld device. There can only ever be an ui session open for the player holding the device.
|
//The network configurator is a handheld device. There can only ever be an ui session open for the player holding the device.
|
||||||
_uiSystem.GetUiOrNull(uid, NetworkConfiguratorUiKey.Configure)?.CloseAll();
|
_uiSystem.TryCloseAll(uid, NetworkConfiguratorUiKey.Configure);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMapInit(EntityUid uid, NetworkConfiguratorComponent component, MapInitEvent args)
|
private void OnMapInit(EntityUid uid, NetworkConfiguratorComponent component, MapInitEvent args)
|
||||||
{
|
{
|
||||||
component.Devices.Clear();
|
component.Devices.Clear();
|
||||||
UpdateUiState(uid, component);
|
UpdateListUiState(uid, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TryAddNetworkDevice(EntityUid? targetUid, EntityUid configuratorUid, EntityUid userUid,
|
private void TryAddNetworkDevice(EntityUid? targetUid, EntityUid configuratorUid, EntityUid userUid,
|
||||||
@@ -118,18 +133,65 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
|||||||
_popupSystem.PopupCursor(Loc.GetString("network-configurator-device-saved", ("address", device.Address), ("device", targetUid)),
|
_popupSystem.PopupCursor(Loc.GetString("network-configurator-device-saved", ("address", device.Address), ("device", targetUid)),
|
||||||
userUid, PopupType.Medium);
|
userUid, PopupType.Medium);
|
||||||
|
|
||||||
UpdateUiState(configurator.Owner, configurator);
|
UpdateListUiState(configurator.Owner, configurator);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TryLinkDevice(EntityUid uid, NetworkConfiguratorComponent configurator, EntityUid? target, EntityUid user)
|
||||||
|
{
|
||||||
|
if (!HasComp<DeviceLinkSourceComponent>(target) && !HasComp<DeviceLinkSinkComponent>(target))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (configurator.ActiveDeviceLink == target)
|
||||||
|
{
|
||||||
|
_popupSystem.PopupEntity(Loc.GetString("network-configurator-link-mode-stopped"), target.Value, user);
|
||||||
|
configurator.ActiveDeviceLink = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HasComp<DeviceLinkSourceComponent>(target) && HasComp<DeviceLinkSourceComponent>(configurator.ActiveDeviceLink)
|
||||||
|
|| HasComp<DeviceLinkSinkComponent>(target) && HasComp<DeviceLinkSinkComponent>(configurator.ActiveDeviceLink))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configurator.ActiveDeviceLink.HasValue)
|
||||||
|
{
|
||||||
|
OpenDeviceLinkUi( uid, target, user, configurator);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_popupSystem.PopupEntity(Loc.GetString("network-configurator-link-mode-started", ("device", Name(target.Value))), target.Value, user);
|
||||||
|
configurator.ActiveDeviceLink = target;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TryLinkDefaults(EntityUid uid, NetworkConfiguratorComponent configurator, EntityUid? targetUid, EntityUid user)
|
||||||
|
{
|
||||||
|
if (!configurator.LinkModeActive || !configurator.ActiveDeviceLink.HasValue
|
||||||
|
|| !targetUid.HasValue || configurator.ActiveDeviceLink == targetUid)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!HasComp<DeviceLinkSourceComponent>(targetUid) && !HasComp<DeviceLinkSinkComponent>(targetUid))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (TryComp(configurator.ActiveDeviceLink, out DeviceLinkSourceComponent? activeSource) && TryComp(targetUid, out DeviceLinkSinkComponent? targetSink))
|
||||||
|
{
|
||||||
|
_deviceLinkSystem.LinkDefaults(user, configurator.ActiveDeviceLink.Value, targetUid.Value, activeSource, targetSink);
|
||||||
|
}
|
||||||
|
else if (TryComp(configurator.ActiveDeviceLink, out DeviceLinkSinkComponent? activeSink) && TryComp(targetUid, out DeviceLinkSourceComponent? targetSource))
|
||||||
|
{
|
||||||
|
_deviceLinkSystem.LinkDefaults(user, targetUid.Value, configurator.ActiveDeviceLink.Value, targetSource, activeSink);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool AccessCheck(EntityUid target, EntityUid? user, NetworkConfiguratorComponent component)
|
private bool AccessCheck(EntityUid target, EntityUid? user, NetworkConfiguratorComponent component)
|
||||||
{
|
{
|
||||||
if (!TryComp(target, out AccessReaderComponent? reader) || user == null)
|
if (!TryComp(target, out AccessReaderComponent? reader) || user == null)
|
||||||
return false;
|
return true;
|
||||||
|
|
||||||
if (_accessSystem.IsAllowed(user.Value, reader))
|
if (_accessSystem.IsAllowed(user.Value, reader))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
SoundSystem.Play(component.SoundNoAccess.GetSound(), Filter.Pvs(user.Value), target, AudioParams.Default.WithVolume(-2f).WithPitchScale(1.2f));
|
_audioSystem.PlayPvs(component.SoundNoAccess, user.Value, AudioParams.Default.WithVolume(-2f).WithPitchScale(1.2f));
|
||||||
_popupSystem.PopupEntity(Loc.GetString("network-configurator-device-access-denied"), target, user.Value);
|
_popupSystem.PopupEntity(Loc.GetString("network-configurator-device-access-denied"), target, user.Value);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
@@ -137,26 +199,80 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
|||||||
|
|
||||||
private void OnComponentRemoved(EntityUid uid, DeviceListComponent component, ComponentRemove args)
|
private void OnComponentRemoved(EntityUid uid, DeviceListComponent component, ComponentRemove args)
|
||||||
{
|
{
|
||||||
_uiSystem.GetUiOrNull(uid, NetworkConfiguratorUiKey.Configure)?.CloseAll();
|
_uiSystem.TryCloseAll(uid, NetworkConfiguratorUiKey.Configure);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SwitchMode(EntityUid? userUid, EntityUid configuratorUid, NetworkConfiguratorComponent configurator)
|
||||||
|
{
|
||||||
|
if (Delay(configurator))
|
||||||
|
return;
|
||||||
|
|
||||||
|
configurator.LinkModeActive = !configurator.LinkModeActive;
|
||||||
|
|
||||||
|
if (!userUid.HasValue)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!configurator.LinkModeActive)
|
||||||
|
configurator.ActiveDeviceLink = null;
|
||||||
|
|
||||||
|
var locString = configurator.LinkModeActive ? "network-configurator-mode-link" : "network-configurator-mode-list";
|
||||||
|
_popupSystem.PopupEntity(Loc.GetString("network-configurator-switched-mode", ("mode", Loc.GetString(locString))),
|
||||||
|
configuratorUid, userUid.Value);
|
||||||
|
|
||||||
|
Dirty(configurator);
|
||||||
|
_appearanceSystem.SetData(configuratorUid, NetworkConfiguratorVisuals.Mode, configurator.LinkModeActive);
|
||||||
|
|
||||||
|
var pitch = configurator.LinkModeActive ? 1 : 0.8f;
|
||||||
|
_audioSystem.PlayPvs(configurator.SoundSwitchMode, userUid.Value, AudioParams.Default.WithVolume(1.5f).WithPitchScale(pitch));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns true if the last time this method was called is earlier than the configurators use delay.
|
||||||
|
/// </summary>
|
||||||
|
private bool Delay(NetworkConfiguratorComponent configurator)
|
||||||
|
{
|
||||||
|
var currentTime = _gameTiming.CurTime;
|
||||||
|
if (currentTime < configurator.LastUseAttempt + configurator.UseDelay)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
configurator.LastUseAttempt = currentTime;
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Interactions
|
#region Interactions
|
||||||
|
|
||||||
|
private void DoExamine(EntityUid uid, NetworkConfiguratorComponent component, ExaminedEvent args)
|
||||||
|
{
|
||||||
|
var mode = component.LinkModeActive ? "network-configurator-examine-mode-link" : "network-configurator-examine-mode-list";
|
||||||
|
args.PushMarkup(Loc.GetString("network-configurator-examine-current-mode", ("mode", Loc.GetString(mode))));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void AfterInteract(EntityUid uid, NetworkConfiguratorComponent component, AfterInteractEvent args)
|
||||||
|
{
|
||||||
|
OnUsed(uid, component, args.Target, args.User, args.CanReach);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Either adds a device to the device list or shows the config ui if the target is ant entity with a device list
|
/// Either adds a device to the device list or shows the config ui if the target is ant entity with a device list
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnUsed(EntityUid uid, NetworkConfiguratorComponent component, EntityUid? target, EntityUid user, bool canReach = true)
|
private void OnUsed(EntityUid uid, NetworkConfiguratorComponent configurator, EntityUid? target, EntityUid user, bool canReach = true)
|
||||||
{
|
{
|
||||||
if (!canReach)
|
if (!canReach || !target.HasValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!HasComp<DeviceListComponent>(target))
|
if (configurator.LinkModeActive)
|
||||||
{
|
{
|
||||||
TryAddNetworkDevice(target, user, component);
|
TryLinkDevice(uid, configurator, target, user);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
OpenDeviceListUi(target, user, component);
|
if (!HasComp<DeviceListComponent>(target))
|
||||||
|
{
|
||||||
|
TryAddNetworkDevice(target, user, configurator);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenDeviceListUi(target, user, configurator);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
@@ -166,22 +282,32 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds the interaction verb which is either configuring device lists or saving a device onto the configurator
|
/// Adds the interaction verb which is either configuring device lists or saving a device onto the configurator
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnAddInteractVerb(EntityUid uid, NetworkConfiguratorComponent component, GetVerbsEvent<UtilityVerb> args)
|
private void OnAddInteractVerb(EntityUid uid, NetworkConfiguratorComponent configurator, GetVerbsEvent<UtilityVerb> args)
|
||||||
{
|
{
|
||||||
if (!args.CanAccess || !args.CanInteract || !args.Using.HasValue || !HasComp<DeviceNetworkComponent>(args.Target))
|
if (!args.CanAccess || !args.CanInteract || !args.Using.HasValue)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
var isDeviceList = HasComp<DeviceListComponent>(args.Target);
|
var verb = new UtilityVerb
|
||||||
|
|
||||||
UtilityVerb verb = new()
|
|
||||||
{
|
{
|
||||||
Text = Loc.GetString(isDeviceList ? "network-configurator-configure" : "network-configurator-save-device"),
|
Act = () => OnUsed(uid, configurator, args.Target, args.User),
|
||||||
Icon = isDeviceList ?
|
|
||||||
new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/settings.svg.192dpi.png")) :
|
|
||||||
new SpriteSpecifier.Texture(new ("/Textures/Interface/VerbIcons/in.svg.192dpi.png")),
|
|
||||||
Act = () => OnUsed(uid, component, args.Target, args.User),
|
|
||||||
Impact = LogImpact.Low
|
Impact = LogImpact.Low
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (configurator.LinkModeActive)
|
||||||
|
{
|
||||||
|
var linkStarted = configurator.ActiveDeviceLink.HasValue;
|
||||||
|
verb.Text = Loc.GetString(linkStarted ? "network-configurator-link" : "network-configurator-start-link");
|
||||||
|
verb.Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/in.svg.192dpi.png"));
|
||||||
|
}
|
||||||
|
else if (!HasComp<DeviceNetworkComponent>(args.Target))
|
||||||
|
{
|
||||||
|
var isDeviceList = HasComp<DeviceListComponent>(args.Target);
|
||||||
|
verb.Text = Loc.GetString(isDeviceList ? "network-configurator-configure" : "network-configurator-save-device");
|
||||||
|
verb.Icon = isDeviceList
|
||||||
|
? new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/settings.svg.192dpi.png"))
|
||||||
|
: new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/in.svg.192dpi.png"));
|
||||||
|
}
|
||||||
|
|
||||||
args.Verbs.Add(verb);
|
args.Verbs.Add(verb);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -193,8 +319,39 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnAddAlternativeSaveDeviceVerb(EntityUid uid, DeviceNetworkComponent component, GetVerbsEvent<AlternativeVerb> args)
|
private void OnAddAlternativeSaveDeviceVerb(EntityUid uid, DeviceNetworkComponent component, GetVerbsEvent<AlternativeVerb> args)
|
||||||
{
|
{
|
||||||
if (!args.CanAccess || !args.CanInteract || !args.Using.HasValue || !HasComp<NetworkConfiguratorComponent>(args.Using.Value)
|
if (!args.CanAccess || !args.CanInteract || !args.Using.HasValue
|
||||||
|| !HasComp<DeviceListComponent>(args.Target))
|
|| !TryComp<NetworkConfiguratorComponent>(args.Using.Value, out var configurator))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!configurator.LinkModeActive && HasComp<DeviceListComponent>(args.Target))
|
||||||
|
{
|
||||||
|
AlternativeVerb verb = new()
|
||||||
|
{
|
||||||
|
Text = Loc.GetString("network-configurator-save-device"),
|
||||||
|
Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/in.svg.192dpi.png")),
|
||||||
|
Act = () => TryAddNetworkDevice(args.Target, args.Using.Value, args.User),
|
||||||
|
Impact = LogImpact.Low
|
||||||
|
};
|
||||||
|
args.Verbs.Add(verb);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (configurator is {LinkModeActive: true, ActiveDeviceLink: { }} && (HasComp<DeviceLinkSinkComponent>(args.Target) || HasComp<DeviceLinkSourceComponent>(args.Target)))
|
||||||
|
{
|
||||||
|
AlternativeVerb verb = new()
|
||||||
|
{
|
||||||
|
Text = Loc.GetString("network-configurator-link-defaults"),
|
||||||
|
Icon = new SpriteSpecifier.Texture(new ResPath("/Textures/Interface/VerbIcons/in.svg.192dpi.png")),
|
||||||
|
Act = () => TryLinkDefaults(args.Using.Value, configurator, args.Target, args.User),
|
||||||
|
Impact = LogImpact.Low
|
||||||
|
};
|
||||||
|
args.Verbs.Add(verb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAddSwitchModeVerb(EntityUid uid, NetworkConfiguratorComponent configurator, GetVerbsEvent<AlternativeVerb> args)
|
||||||
|
{
|
||||||
|
if (!args.CanAccess || !args.CanInteract || !args.Using.HasValue || !HasComp<NetworkConfiguratorComponent>(args.Target))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
AlternativeVerb verb = new()
|
AlternativeVerb verb = new()
|
||||||
@@ -211,11 +368,57 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
|||||||
|
|
||||||
#region UI
|
#region UI
|
||||||
|
|
||||||
|
private void OpenDeviceLinkUi(EntityUid configuratorUid, EntityUid? targetUid, EntityUid userUid, NetworkConfiguratorComponent configurator)
|
||||||
|
{
|
||||||
|
if (Delay(configurator))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!targetUid.HasValue || !configurator.ActiveDeviceLink.HasValue || !TryComp(userUid, out ActorComponent? actor) || !AccessCheck(targetUid.Value, userUid, configurator))
|
||||||
|
return;
|
||||||
|
|
||||||
|
|
||||||
|
_uiSystem.TryOpen(configuratorUid, NetworkConfiguratorUiKey.Link, actor.PlayerSession);
|
||||||
|
configurator.DeviceLinkTarget = targetUid;
|
||||||
|
|
||||||
|
|
||||||
|
if (TryComp(configurator.ActiveDeviceLink, out DeviceLinkSourceComponent? activeSource) && TryComp(targetUid, out DeviceLinkSinkComponent? targetSink))
|
||||||
|
{
|
||||||
|
UpdateLinkUiState(configuratorUid, configurator.ActiveDeviceLink.Value, targetUid.Value, activeSource, targetSink);
|
||||||
|
}
|
||||||
|
else if (TryComp(configurator.ActiveDeviceLink, out DeviceLinkSinkComponent? activeSink)
|
||||||
|
&& TryComp(targetUid, out DeviceLinkSourceComponent? targetSource))
|
||||||
|
{
|
||||||
|
UpdateLinkUiState(configuratorUid, targetUid.Value, configurator.ActiveDeviceLink.Value, targetSource, activeSink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateLinkUiState(EntityUid configuratorUid, EntityUid sourceUid, EntityUid sinkUid,
|
||||||
|
DeviceLinkSourceComponent? sourceComponent = null, DeviceLinkSinkComponent? sinkComponent = null,
|
||||||
|
DeviceNetworkComponent? sourceNetworkComponent = null, DeviceNetworkComponent? sinkNetworkComponent = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(sourceUid, ref sourceComponent) || !Resolve(sinkUid, ref sinkComponent))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var sources = _deviceLinkSystem.GetSourcePorts(sourceUid, sourceComponent);
|
||||||
|
var sinks = _deviceLinkSystem.GetSinkPorts(sinkUid, sinkComponent);
|
||||||
|
var links = _deviceLinkSystem.GetLinks(sourceUid, sinkUid, sourceComponent);
|
||||||
|
var defaults = _deviceLinkSystem.GetDefaults(sources);
|
||||||
|
|
||||||
|
var sourceAddress = Resolve(sourceUid, ref sourceNetworkComponent) ? sourceNetworkComponent.Address : "";
|
||||||
|
var sinkAddress = Resolve(sinkUid, ref sinkNetworkComponent) ? sinkNetworkComponent.Address : "";
|
||||||
|
|
||||||
|
var state = new DeviceLinkUserInterfaceState(sources, sinks, links, sourceAddress, sinkAddress, defaults);
|
||||||
|
_uiSystem.TrySetUiState(configuratorUid, NetworkConfiguratorUiKey.Link, state);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Opens the config ui. It can be used to modify the devices in the targets device list.
|
/// Opens the config ui. It can be used to modify the devices in the targets device list.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void OpenDeviceListUi(EntityUid? targetUid, EntityUid userUid, NetworkConfiguratorComponent configurator)
|
private void OpenDeviceListUi(EntityUid? targetUid, EntityUid userUid, NetworkConfiguratorComponent configurator)
|
||||||
{
|
{
|
||||||
|
if (Delay(configurator))
|
||||||
|
return;
|
||||||
|
|
||||||
if (!targetUid.HasValue || !TryComp(userUid, out ActorComponent? actor) || !AccessCheck(targetUid.Value, userUid, configurator))
|
if (!targetUid.HasValue || !TryComp(userUid, out ActorComponent? actor) || !AccessCheck(targetUid.Value, userUid, configurator))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@@ -233,7 +436,7 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sends the list of saved devices to the ui
|
/// Sends the list of saved devices to the ui
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void UpdateUiState(EntityUid uid, NetworkConfiguratorComponent component)
|
private void UpdateListUiState(EntityUid uid, NetworkConfiguratorComponent component)
|
||||||
{
|
{
|
||||||
HashSet<(string address, string name)> devices = new();
|
HashSet<(string address, string name)> devices = new();
|
||||||
HashSet<string> invalidDevices = new();
|
HashSet<string> invalidDevices = new();
|
||||||
@@ -264,6 +467,12 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
|||||||
private void OnUiClosed(EntityUid uid, NetworkConfiguratorComponent component, BoundUIClosedEvent args)
|
private void OnUiClosed(EntityUid uid, NetworkConfiguratorComponent component, BoundUIClosedEvent args)
|
||||||
{
|
{
|
||||||
component.ActiveDeviceList = null;
|
component.ActiveDeviceList = null;
|
||||||
|
|
||||||
|
if (args.UiKey is NetworkConfiguratorUiKey.Link)
|
||||||
|
{
|
||||||
|
component.ActiveDeviceLink = null;
|
||||||
|
component.DeviceLinkTarget = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -272,7 +481,7 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
|||||||
private void OnRemoveDevice(EntityUid uid, NetworkConfiguratorComponent component, NetworkConfiguratorRemoveDeviceMessage args)
|
private void OnRemoveDevice(EntityUid uid, NetworkConfiguratorComponent component, NetworkConfiguratorRemoveDeviceMessage args)
|
||||||
{
|
{
|
||||||
component.Devices.Remove(args.Address);
|
component.Devices.Remove(args.Address);
|
||||||
UpdateUiState(uid, component);
|
UpdateListUiState(uid, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -281,7 +490,61 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
|||||||
private void OnClearDevice(EntityUid uid, NetworkConfiguratorComponent component, NetworkConfiguratorClearDevicesMessage _)
|
private void OnClearDevice(EntityUid uid, NetworkConfiguratorComponent component, NetworkConfiguratorClearDevicesMessage _)
|
||||||
{
|
{
|
||||||
component.Devices.Clear();
|
component.Devices.Clear();
|
||||||
UpdateUiState(uid, component);
|
UpdateListUiState(uid, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnClearLinks(EntityUid uid, NetworkConfiguratorComponent configurator, NetworkConfiguratorClearLinksMessage args)
|
||||||
|
{
|
||||||
|
if (!configurator.ActiveDeviceLink.HasValue || !configurator.DeviceLinkTarget.HasValue)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (HasComp<DeviceLinkSourceComponent>(configurator.ActiveDeviceLink))
|
||||||
|
{
|
||||||
|
_deviceLinkSystem.RemoveSinkFromSource(configurator.ActiveDeviceLink.Value, configurator.DeviceLinkTarget.Value);
|
||||||
|
UpdateLinkUiState(uid, configurator.ActiveDeviceLink.Value, configurator.DeviceLinkTarget.Value);
|
||||||
|
}
|
||||||
|
else if (HasComp<DeviceLinkSourceComponent>(configurator.DeviceLinkTarget))
|
||||||
|
{
|
||||||
|
_deviceLinkSystem.RemoveSinkFromSource(configurator.DeviceLinkTarget.Value, configurator.ActiveDeviceLink.Value);
|
||||||
|
UpdateLinkUiState(uid, configurator.DeviceLinkTarget.Value, configurator.ActiveDeviceLink.Value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnToggleLinks(EntityUid uid, NetworkConfiguratorComponent configurator, NetworkConfiguratorToggleLinkMessage args)
|
||||||
|
{
|
||||||
|
if (!configurator.ActiveDeviceLink.HasValue || !configurator.DeviceLinkTarget.HasValue)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (TryComp(configurator.ActiveDeviceLink, out DeviceLinkSourceComponent? activeSource))
|
||||||
|
{
|
||||||
|
_deviceLinkSystem.ToggleLink(args.Session.AttachedEntity, configurator.ActiveDeviceLink.Value, configurator.DeviceLinkTarget.Value, args.Source, args.Sink, activeSource);
|
||||||
|
UpdateLinkUiState(uid, configurator.ActiveDeviceLink.Value, configurator.DeviceLinkTarget.Value, activeSource);
|
||||||
|
}
|
||||||
|
else if (TryComp(configurator.DeviceLinkTarget, out DeviceLinkSourceComponent? targetSource))
|
||||||
|
{
|
||||||
|
_deviceLinkSystem.ToggleLink(args.Session.AttachedEntity, configurator.DeviceLinkTarget.Value, configurator.ActiveDeviceLink.Value, args.Source, args.Sink, targetSource);
|
||||||
|
UpdateLinkUiState(uid, configurator.DeviceLinkTarget.Value, configurator.ActiveDeviceLink.Value, targetSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves links set by the device link UI
|
||||||
|
/// </summary>
|
||||||
|
private void OnSaveLinks(EntityUid uid, NetworkConfiguratorComponent configurator, NetworkConfiguratorLinksSaveMessage args)
|
||||||
|
{
|
||||||
|
if (!configurator.ActiveDeviceLink.HasValue || !configurator.DeviceLinkTarget.HasValue)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (TryComp(configurator.ActiveDeviceLink, out DeviceLinkSourceComponent? activeSource))
|
||||||
|
{
|
||||||
|
_deviceLinkSystem.SaveLinks(args.Session.AttachedEntity, configurator.ActiveDeviceLink.Value, configurator.DeviceLinkTarget.Value, args.Links, activeSource);
|
||||||
|
UpdateLinkUiState(uid, configurator.ActiveDeviceLink.Value, configurator.DeviceLinkTarget.Value, activeSource);
|
||||||
|
}
|
||||||
|
else if (TryComp(configurator.DeviceLinkTarget, out DeviceLinkSourceComponent? targetSource))
|
||||||
|
{
|
||||||
|
_deviceLinkSystem.SaveLinks(args.Session.AttachedEntity, configurator.DeviceLinkTarget.Value, configurator.ActiveDeviceLink.Value, args.Links, targetSource);
|
||||||
|
UpdateLinkUiState(uid, configurator.DeviceLinkTarget.Value, configurator.ActiveDeviceLink.Value, targetSource);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -307,11 +570,9 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
|||||||
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);
|
UpdateListUiState(uid, component);
|
||||||
return;
|
return;
|
||||||
case NetworkConfiguratorButtonKey.Show:
|
case NetworkConfiguratorButtonKey.Show:
|
||||||
// This should be done client-side.
|
|
||||||
// _deviceListSystem.ToggleVisualization(component.ActiveDeviceList.Value);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -330,5 +591,11 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
|||||||
_deviceListSystem.GetDeviceList(component.ActiveDeviceList.Value)
|
_deviceListSystem.GetDeviceList(component.ActiveDeviceList.Value)
|
||||||
.Select(v => (v.Key, MetaData(v.Value).EntityName)).ToHashSet()));
|
.Select(v => (v.Key, MetaData(v.Value).EntityName)).ToHashSet()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnUiOpenAttempt(EntityUid uid, NetworkConfiguratorComponent configurator, ActivatableUIOpenAttemptEvent args)
|
||||||
|
{
|
||||||
|
if (configurator.LinkModeActive)
|
||||||
|
args.Cancel();
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Content.Server.DeviceLinking.Events;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Server.Power.EntitySystems;
|
using Content.Server.Power.EntitySystems;
|
||||||
using Content.Shared.Tools.Components;
|
using Content.Shared.Tools.Components;
|
||||||
@@ -8,7 +9,6 @@ using Content.Shared.Doors.Systems;
|
|||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Content.Shared.Wires;
|
using Content.Shared.Wires;
|
||||||
using Content.Server.MachineLinking.Events;
|
|
||||||
using Content.Server.MachineLinking.System;
|
using Content.Server.MachineLinking.System;
|
||||||
|
|
||||||
namespace Content.Server.Doors.Systems
|
namespace Content.Server.Doors.Systems
|
||||||
@@ -44,7 +44,7 @@ namespace Content.Server.Doors.Systems
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSignalReceived(EntityUid uid, AirlockComponent component, SignalReceivedEvent args)
|
private void OnSignalReceived(EntityUid uid, AirlockComponent component, ref SignalReceivedEvent args)
|
||||||
{
|
{
|
||||||
if (args.Port == component.AutoClosePort)
|
if (args.Port == component.AutoClosePort)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,20 +1,19 @@
|
|||||||
|
using Content.Server.DeviceLinking.Events;
|
||||||
|
using Content.Server.DeviceLinking.Systems;
|
||||||
using Content.Server.Explosion.Components;
|
using Content.Server.Explosion.Components;
|
||||||
using Content.Server.MachineLinking.Events;
|
|
||||||
using Content.Server.MachineLinking.System;
|
|
||||||
|
|
||||||
namespace Content.Server.Explosion.EntitySystems
|
namespace Content.Server.Explosion.EntitySystems
|
||||||
{
|
{
|
||||||
public sealed partial class TriggerSystem
|
public sealed partial class TriggerSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
|
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
||||||
|
|
||||||
private void InitializeSignal()
|
private void InitializeSignal()
|
||||||
{
|
{
|
||||||
SubscribeLocalEvent<TriggerOnSignalComponent,SignalReceivedEvent>(OnSignalReceived);
|
SubscribeLocalEvent<TriggerOnSignalComponent,SignalReceivedEvent>(OnSignalReceived);
|
||||||
SubscribeLocalEvent<TriggerOnSignalComponent,ComponentInit>(OnInit);
|
SubscribeLocalEvent<TriggerOnSignalComponent,ComponentInit>(OnInit);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSignalReceived(EntityUid uid, TriggerOnSignalComponent component, SignalReceivedEvent args)
|
private void OnSignalReceived(EntityUid uid, TriggerOnSignalComponent component, ref SignalReceivedEvent args)
|
||||||
{
|
{
|
||||||
if (args.Port != component.Port)
|
if (args.Port != component.Port)
|
||||||
return;
|
return;
|
||||||
@@ -23,7 +22,7 @@ namespace Content.Server.Explosion.EntitySystems
|
|||||||
}
|
}
|
||||||
private void OnInit(EntityUid uid, TriggerOnSignalComponent component, ComponentInit args)
|
private void OnInit(EntityUid uid, TriggerOnSignalComponent component, ComponentInit args)
|
||||||
{
|
{
|
||||||
_signalSystem.EnsureReceiverPorts(uid, component.Port);
|
_signalSystem.EnsureSinkPorts(uid, component.Port);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,8 +3,6 @@ using Content.Server.DeviceNetwork;
|
|||||||
using Content.Server.DeviceNetwork.Systems;
|
using Content.Server.DeviceNetwork.Systems;
|
||||||
using Content.Server.Ghost;
|
using Content.Server.Ghost;
|
||||||
using Content.Server.Light.Components;
|
using Content.Server.Light.Components;
|
||||||
using Content.Server.MachineLinking.Events;
|
|
||||||
using Content.Server.MachineLinking.System;
|
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Server.Temperature.Components;
|
using Content.Server.Temperature.Components;
|
||||||
using Content.Shared.Audio;
|
using Content.Shared.Audio;
|
||||||
@@ -22,6 +20,8 @@ using Robust.Shared.Player;
|
|||||||
using Robust.Shared.Timing;
|
using Robust.Shared.Timing;
|
||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Server.Emp;
|
using Content.Server.Emp;
|
||||||
|
using Content.Server.DeviceLinking.Events;
|
||||||
|
using Content.Server.DeviceLinking.Systems;
|
||||||
|
|
||||||
namespace Content.Server.Light.EntitySystems
|
namespace Content.Server.Light.EntitySystems
|
||||||
{
|
{
|
||||||
@@ -37,7 +37,7 @@ namespace Content.Server.Light.EntitySystems
|
|||||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||||
[Dependency] private readonly IAdminLogManager _adminLogger= default!;
|
[Dependency] private readonly IAdminLogManager _adminLogger= default!;
|
||||||
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
[Dependency] private readonly SharedHandsSystem _handsSystem = default!;
|
||||||
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
|
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
||||||
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
||||||
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
[Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!;
|
||||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
@@ -69,7 +69,7 @@ namespace Content.Server.Light.EntitySystems
|
|||||||
private void OnInit(EntityUid uid, PoweredLightComponent light, ComponentInit args)
|
private void OnInit(EntityUid uid, PoweredLightComponent light, ComponentInit args)
|
||||||
{
|
{
|
||||||
light.LightBulbContainer = _containerSystem.EnsureContainer<ContainerSlot>(uid, LightBulbContainer);
|
light.LightBulbContainer = _containerSystem.EnsureContainer<ContainerSlot>(uid, LightBulbContainer);
|
||||||
_signalSystem.EnsureReceiverPorts(uid, light.OnPort, light.OffPort, light.TogglePort);
|
_signalSystem.EnsureSinkPorts(uid, light.OnPort, light.OffPort, light.TogglePort);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMapInit(EntityUid uid, PoweredLightComponent light, MapInitEvent args)
|
private void OnMapInit(EntityUid uid, PoweredLightComponent light, MapInitEvent args)
|
||||||
@@ -354,7 +354,7 @@ namespace Content.Server.Light.EntitySystems
|
|||||||
_appearance.SetData(uid, PoweredLightVisuals.Blinking, isNowBlinking, appearance);
|
_appearance.SetData(uid, PoweredLightVisuals.Blinking, isNowBlinking, appearance);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSignalReceived(EntityUid uid, PoweredLightComponent component, SignalReceivedEvent args)
|
private void OnSignalReceived(EntityUid uid, PoweredLightComponent component, ref SignalReceivedEvent args)
|
||||||
{
|
{
|
||||||
if (args.Port == component.OffPort)
|
if (args.Port == component.OffPort)
|
||||||
SetState(uid, false, component);
|
SetState(uid, false, component);
|
||||||
|
|||||||
@@ -3,13 +3,13 @@ using Content.Server.MachineLinking.System;
|
|||||||
namespace Content.Server.MachineLinking.Components
|
namespace Content.Server.MachineLinking.Components
|
||||||
{
|
{
|
||||||
[DataDefinition]
|
[DataDefinition]
|
||||||
public struct PortIdentifier
|
public readonly struct PortIdentifier
|
||||||
{
|
{
|
||||||
[DataField("uid")]
|
[DataField("uid")]
|
||||||
public EntityUid Uid;
|
public readonly EntityUid Uid;
|
||||||
|
|
||||||
[DataField("port")]
|
[DataField("port")]
|
||||||
public string Port;
|
public readonly string Port;
|
||||||
|
|
||||||
public PortIdentifier(EntityUid uid, string port)
|
public PortIdentifier(EntityUid uid, string port)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
namespace Content.Server.MachineLinking.Events
|
|
||||||
{
|
|
||||||
public sealed class SignalReceivedEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
public readonly string Port;
|
|
||||||
public readonly EntityUid? Trigger;
|
|
||||||
|
|
||||||
public SignalReceivedEvent(string port, EntityUid? trigger)
|
|
||||||
{
|
|
||||||
Port = port;
|
|
||||||
Trigger = trigger;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,18 +1,16 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using Content.Server.DeviceLinking.Events;
|
||||||
using Content.Server.MachineLinking.Components;
|
using Content.Server.MachineLinking.Components;
|
||||||
using Content.Server.MachineLinking.Events;
|
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Server.Tools;
|
using Content.Server.Tools;
|
||||||
|
using Content.Shared.DeviceLinking.Events;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.MachineLinking;
|
using Content.Shared.MachineLinking;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.Player;
|
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Content.Shared.MachineLinking.Events;
|
|
||||||
using Content.Server.Database;
|
|
||||||
|
|
||||||
namespace Content.Server.MachineLinking.System
|
namespace Content.Server.MachineLinking.System
|
||||||
{
|
{
|
||||||
@@ -140,7 +138,10 @@ namespace Content.Server.MachineLinking.System
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
foreach (var receiver in receivers)
|
foreach (var receiver in receivers)
|
||||||
RaiseLocalEvent(receiver.Uid, new SignalReceivedEvent(receiver.Port, uid), false);
|
{
|
||||||
|
var eventArgs = new SignalReceivedEvent(receiver.Port, uid);
|
||||||
|
RaiseLocalEvent(receiver.Uid, ref eventArgs);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTransmitterStartup(EntityUid uid, SignalTransmitterComponent transmitter, ComponentStartup args)
|
private void OnTransmitterStartup(EntityUid uid, SignalTransmitterComponent transmitter, ComponentStartup args)
|
||||||
|
|||||||
@@ -1,30 +1,28 @@
|
|||||||
using Content.Server.Climbing;
|
using Content.Server.Climbing;
|
||||||
using Content.Server.Cloning;
|
using Content.Server.Cloning;
|
||||||
using Content.Server.Medical.Components;
|
using Content.Server.Medical.Components;
|
||||||
using Content.Server.Power.Components;
|
|
||||||
using Content.Shared.Destructible;
|
using Content.Shared.Destructible;
|
||||||
using Content.Shared.ActionBlocker;
|
using Content.Shared.ActionBlocker;
|
||||||
using Content.Shared.DragDrop;
|
using Content.Shared.DragDrop;
|
||||||
using Content.Shared.Movement.Events;
|
using Content.Shared.Movement.Events;
|
||||||
using Content.Shared.Verbs;
|
using Content.Shared.Verbs;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Content.Server.MachineLinking.System;
|
|
||||||
using Content.Server.MachineLinking.Events;
|
|
||||||
using Content.Server.Cloning.Components;
|
using Content.Server.Cloning.Components;
|
||||||
using Content.Server.Construction;
|
using Content.Server.Construction;
|
||||||
|
using Content.Server.DeviceLinking.Systems;
|
||||||
|
using Content.Shared.DeviceLinking.Events;
|
||||||
using Content.Server.Power.EntitySystems;
|
using Content.Server.Power.EntitySystems;
|
||||||
using Content.Shared.Body.Components;
|
using Content.Shared.Body.Components;
|
||||||
using Content.Shared.Mobs.Components;
|
using Content.Shared.Mobs.Components;
|
||||||
using Content.Shared.Mobs.Systems;
|
using Content.Shared.Mobs.Systems;
|
||||||
using Robust.Server.Containers;
|
using Robust.Server.Containers;
|
||||||
using Robust.Server.GameObjects;
|
|
||||||
using static Content.Shared.MedicalScanner.SharedMedicalScannerComponent; // Hmm...
|
using static Content.Shared.MedicalScanner.SharedMedicalScannerComponent; // Hmm...
|
||||||
|
|
||||||
namespace Content.Server.Medical
|
namespace Content.Server.Medical
|
||||||
{
|
{
|
||||||
public sealed class MedicalScannerSystem : EntitySystem
|
public sealed class MedicalScannerSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
|
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
||||||
[Dependency] private readonly ActionBlockerSystem _blocker = default!;
|
[Dependency] private readonly ActionBlockerSystem _blocker = default!;
|
||||||
[Dependency] private readonly ClimbSystem _climbSystem = default!;
|
[Dependency] private readonly ClimbSystem _climbSystem = default!;
|
||||||
[Dependency] private readonly CloningConsoleSystem _cloningConsoleSystem = default!;
|
[Dependency] private readonly CloningConsoleSystem _cloningConsoleSystem = default!;
|
||||||
@@ -70,7 +68,7 @@ namespace Content.Server.Medical
|
|||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
scannerComponent.BodyContainer = _containerSystem.EnsureContainer<ContainerSlot>(uid, $"scanner-bodyContainer");
|
scannerComponent.BodyContainer = _containerSystem.EnsureContainer<ContainerSlot>(uid, $"scanner-bodyContainer");
|
||||||
_signalSystem.EnsureReceiverPorts(uid, MedicalScannerComponent.ScannerPort);
|
_signalSystem.EnsureSinkPorts(uid, MedicalScannerComponent.ScannerPort);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnRelayMovement(EntityUid uid, MedicalScannerComponent scannerComponent, ref ContainerRelayMovementEntityEvent args)
|
private void OnRelayMovement(EntityUid uid, MedicalScannerComponent scannerComponent, ref ContainerRelayMovementEntityEvent args)
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
using Content.Server.MachineLinking.Events;
|
|
||||||
|
using Content.Server.DeviceLinking.Events;
|
||||||
|
using Content.Server.DeviceLinking.Systems;
|
||||||
using Content.Server.MachineLinking.System;
|
using Content.Server.MachineLinking.System;
|
||||||
using Content.Server.Materials;
|
using Content.Server.Materials;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
@@ -9,7 +11,6 @@ using Content.Shared.Physics.Controllers;
|
|||||||
using Robust.Shared.Physics;
|
using Robust.Shared.Physics;
|
||||||
using Robust.Shared.Physics.Collision.Shapes;
|
using Robust.Shared.Physics.Collision.Shapes;
|
||||||
using Robust.Shared.Physics.Components;
|
using Robust.Shared.Physics.Components;
|
||||||
using Robust.Shared.Physics.Dynamics;
|
|
||||||
using Robust.Shared.Physics.Systems;
|
using Robust.Shared.Physics.Systems;
|
||||||
|
|
||||||
namespace Content.Server.Physics.Controllers;
|
namespace Content.Server.Physics.Controllers;
|
||||||
@@ -17,8 +18,8 @@ namespace Content.Server.Physics.Controllers;
|
|||||||
public sealed class ConveyorController : SharedConveyorController
|
public sealed class ConveyorController : SharedConveyorController
|
||||||
{
|
{
|
||||||
[Dependency] private readonly FixtureSystem _fixtures = default!;
|
[Dependency] private readonly FixtureSystem _fixtures = default!;
|
||||||
|
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
||||||
[Dependency] private readonly MaterialReclaimerSystem _materialReclaimer = default!;
|
[Dependency] private readonly MaterialReclaimerSystem _materialReclaimer = default!;
|
||||||
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
|
|
||||||
[Dependency] private readonly SharedBroadphaseSystem _broadphase = default!;
|
[Dependency] private readonly SharedBroadphaseSystem _broadphase = default!;
|
||||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||||
|
|
||||||
@@ -37,7 +38,7 @@ public sealed class ConveyorController : SharedConveyorController
|
|||||||
|
|
||||||
private void OnInit(EntityUid uid, ConveyorComponent component, ComponentInit args)
|
private void OnInit(EntityUid uid, ConveyorComponent component, ComponentInit args)
|
||||||
{
|
{
|
||||||
_signalSystem.EnsureReceiverPorts(uid, component.ReversePort, component.ForwardPort, component.OffPort);
|
_signalSystem.EnsureSinkPorts(uid, component.ReversePort, component.ForwardPort, component.OffPort);
|
||||||
|
|
||||||
if (TryComp<PhysicsComponent>(uid, out var physics))
|
if (TryComp<PhysicsComponent>(uid, out var physics))
|
||||||
{
|
{
|
||||||
@@ -76,7 +77,7 @@ public sealed class ConveyorController : SharedConveyorController
|
|||||||
_appearance.SetData(uid, ConveyorVisuals.State, component.Powered ? component.State : ConveyorState.Off);
|
_appearance.SetData(uid, ConveyorVisuals.State, component.Powered ? component.State : ConveyorState.Off);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSignalReceived(EntityUid uid, ConveyorComponent component, SignalReceivedEvent args)
|
private void OnSignalReceived(EntityUid uid, ConveyorComponent component, ref SignalReceivedEvent args)
|
||||||
{
|
{
|
||||||
if (args.Port == component.OffPort)
|
if (args.Port == component.OffPort)
|
||||||
SetState(uid, ConveyorState.Off, component);
|
SetState(uid, ConveyorState.Off, component);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Construction;
|
using Content.Server.Construction;
|
||||||
|
using Content.Server.DeviceLinking.Events;
|
||||||
using Content.Server.MachineLinking.Components;
|
using Content.Server.MachineLinking.Components;
|
||||||
using Content.Server.MachineLinking.Events;
|
|
||||||
using Content.Server.Paper;
|
using Content.Server.Paper;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Server.Research.Systems;
|
using Content.Server.Research.Systems;
|
||||||
@@ -10,7 +10,7 @@ using Content.Server.Xenoarchaeology.Equipment.Components;
|
|||||||
using Content.Server.Xenoarchaeology.XenoArtifacts;
|
using Content.Server.Xenoarchaeology.XenoArtifacts;
|
||||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
using Content.Server.Xenoarchaeology.XenoArtifacts.Events;
|
||||||
using Content.Shared.Audio;
|
using Content.Shared.Audio;
|
||||||
using Content.Shared.MachineLinking.Events;
|
using Content.Shared.DeviceLinking.Events;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Content.Shared.Research.Components;
|
using Content.Shared.Research.Components;
|
||||||
using Content.Shared.Xenoarchaeology.Equipment;
|
using Content.Shared.Xenoarchaeology.Equipment;
|
||||||
@@ -168,10 +168,10 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
|
|||||||
|
|
||||||
private void OnNewLink(EntityUid uid, AnalysisConsoleComponent component, NewLinkEvent args)
|
private void OnNewLink(EntityUid uid, AnalysisConsoleComponent component, NewLinkEvent args)
|
||||||
{
|
{
|
||||||
if (!TryComp<ArtifactAnalyzerComponent>(args.Receiver, out var analyzer))
|
if (!TryComp<ArtifactAnalyzerComponent>(args.Sink, out var analyzer))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
component.AnalyzerEntity = args.Receiver;
|
component.AnalyzerEntity = args.Sink;
|
||||||
analyzer.Console = uid;
|
analyzer.Console = uid;
|
||||||
|
|
||||||
UpdateUserInterface(uid, component);
|
UpdateUserInterface(uid, component);
|
||||||
|
|||||||
@@ -5,9 +5,9 @@ using Content.Shared.Emag.Components;
|
|||||||
using Content.Shared.Emag.Systems;
|
using Content.Shared.Emag.Systems;
|
||||||
using Content.Shared.PDA;
|
using Content.Shared.PDA;
|
||||||
using Content.Shared.Access.Components;
|
using Content.Shared.Access.Components;
|
||||||
|
using Content.Shared.DeviceLinking.Events;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Content.Shared.Hands.EntitySystems;
|
using Content.Shared.Hands.EntitySystems;
|
||||||
using Content.Shared.MachineLinking.Events;
|
|
||||||
using Content.Shared.StationRecords;
|
using Content.Shared.StationRecords;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
|||||||
22
Content.Shared/DeviceLinking/DeviceLinkSinkComponent.cs
Normal file
22
Content.Shared/DeviceLinking/DeviceLinkSinkComponent.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
|
||||||
|
|
||||||
|
namespace Content.Shared.DeviceLinking;
|
||||||
|
|
||||||
|
[RegisterComponent]
|
||||||
|
[NetworkedComponent] // for interactions. Actual state isn't currently synced.
|
||||||
|
[Access(typeof(SharedDeviceLinkSystem))]
|
||||||
|
public sealed class DeviceLinkSinkComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The ports this sink has
|
||||||
|
/// </summary>
|
||||||
|
[DataField("ports", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<SinkPortPrototype>))]
|
||||||
|
public HashSet<string>? Ports;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used for removing a sink from all linked sources when it gets removed
|
||||||
|
/// </summary>
|
||||||
|
[DataField("links")]
|
||||||
|
public HashSet<EntityUid> LinkedSources = new();
|
||||||
|
}
|
||||||
35
Content.Shared/DeviceLinking/DeviceLinkSourceComponent.cs
Normal file
35
Content.Shared/DeviceLinking/DeviceLinkSourceComponent.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
|
||||||
|
|
||||||
|
namespace Content.Shared.DeviceLinking;
|
||||||
|
|
||||||
|
[RegisterComponent]
|
||||||
|
[NetworkedComponent] // for interactions. Actual state isn't currently synced.
|
||||||
|
[Access(typeof(SharedDeviceLinkSystem))]
|
||||||
|
public sealed class DeviceLinkSourceComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The ports the device link source sends signals from
|
||||||
|
/// </summary>
|
||||||
|
[DataField("ports", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<SourcePortPrototype>))]
|
||||||
|
public HashSet<string>? Ports;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A list of sink uids that got linked for each port
|
||||||
|
/// </summary>
|
||||||
|
[DataField("registeredSinks")]
|
||||||
|
public Dictionary<string, HashSet<EntityUid>> Outputs = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of source to sink ports for each linked sink entity for easier managing of links
|
||||||
|
/// </summary>
|
||||||
|
[DataField("linkedPorts")]
|
||||||
|
public Dictionary<EntityUid, HashSet<(string source, string sink)>> LinkedPorts = new();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Limits the range devices can be linked across.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("range")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float Range = 30f;
|
||||||
|
}
|
||||||
46
Content.Shared/DeviceLinking/DevicePortPrototype.cs
Normal file
46
Content.Shared/DeviceLinking/DevicePortPrototype.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
|
||||||
|
|
||||||
|
namespace Content.Shared.DeviceLinking;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A prototype for a device port, for use with device linking.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public abstract class DevicePortPrototype
|
||||||
|
{
|
||||||
|
[IdDataField]
|
||||||
|
public string ID { get; } = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Localization string for the port name. Displayed in the linking UI.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("name", required:true)]
|
||||||
|
public string Name = default!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Localization string for a description of the ports functionality. Should either indicate when a source
|
||||||
|
/// port is fired, or what function a sink port serves. Displayed as a tooltip in the linking UI.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("description", required: true)]
|
||||||
|
public string Description = default!;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Prototype("sinkPort")]
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class SinkPortPrototype : DevicePortPrototype, IPrototype
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
[Prototype("sourcePort")]
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class SourcePortPrototype : DevicePortPrototype, IPrototype
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This is a set of sink ports that this source port will attempt to link to when using the
|
||||||
|
/// default-link functionality.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("defaultLinks", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<SinkPortPrototype>))]
|
||||||
|
public readonly HashSet<string>? DefaultLinks;
|
||||||
|
}
|
||||||
19
Content.Shared/DeviceLinking/Events/LinkAttemptEvent.cs
Normal file
19
Content.Shared/DeviceLinking/Events/LinkAttemptEvent.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
namespace Content.Shared.DeviceLinking.Events;
|
||||||
|
|
||||||
|
public sealed class LinkAttemptEvent : CancellableEntityEventArgs
|
||||||
|
{
|
||||||
|
public readonly EntityUid Source;
|
||||||
|
public readonly EntityUid Sink;
|
||||||
|
public readonly EntityUid? User;
|
||||||
|
public readonly string SourcePort;
|
||||||
|
public readonly string SinkPort;
|
||||||
|
|
||||||
|
public LinkAttemptEvent(EntityUid? user, EntityUid source, string sourcePort, EntityUid sink, string sinkPort)
|
||||||
|
{
|
||||||
|
User = user;
|
||||||
|
Source = source;
|
||||||
|
SourcePort = sourcePort;
|
||||||
|
Sink = sink;
|
||||||
|
SinkPort = sinkPort;
|
||||||
|
}
|
||||||
|
}
|
||||||
19
Content.Shared/DeviceLinking/Events/NewLinkEvent.cs
Normal file
19
Content.Shared/DeviceLinking/Events/NewLinkEvent.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
namespace Content.Shared.DeviceLinking.Events;
|
||||||
|
|
||||||
|
public sealed class NewLinkEvent : EntityEventArgs
|
||||||
|
{
|
||||||
|
public readonly EntityUid Source;
|
||||||
|
public readonly EntityUid Sink;
|
||||||
|
public readonly EntityUid? User;
|
||||||
|
public readonly string SourcePort;
|
||||||
|
public readonly string SinkPort;
|
||||||
|
|
||||||
|
public NewLinkEvent(EntityUid? user, EntityUid source, string sourcePort, EntityUid sink, string sinkPort)
|
||||||
|
{
|
||||||
|
User = user;
|
||||||
|
Source = source;
|
||||||
|
SourcePort = sourcePort;
|
||||||
|
Sink = sink;
|
||||||
|
SinkPort = sinkPort;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
namespace Content.Server.MachineLinking.Events
|
namespace Content.Shared.DeviceLinking.Events
|
||||||
{
|
{
|
||||||
public sealed class PortDisconnectedEvent : EntityEventArgs
|
public sealed class PortDisconnectedEvent : EntityEventArgs
|
||||||
{
|
{
|
||||||
466
Content.Shared/DeviceLinking/SharedDeviceLinkSystem.cs
Normal file
466
Content.Shared/DeviceLinking/SharedDeviceLinkSystem.cs
Normal file
@@ -0,0 +1,466 @@
|
|||||||
|
using Content.Shared.DeviceLinking.Events;
|
||||||
|
using Content.Shared.Popups;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
|
namespace Content.Shared.DeviceLinking;
|
||||||
|
|
||||||
|
public abstract class SharedDeviceLinkSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||||
|
|
||||||
|
public const string InvokedPort = "link_port";
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
SubscribeLocalEvent<DeviceLinkSourceComponent, ComponentStartup>(OnSourceStartup);
|
||||||
|
SubscribeLocalEvent<DeviceLinkSinkComponent, ComponentStartup>(OnSinkStartup);
|
||||||
|
SubscribeLocalEvent<DeviceLinkSourceComponent, ComponentRemove>(OnSourceRemoved);
|
||||||
|
SubscribeLocalEvent<DeviceLinkSinkComponent, ComponentRemove>(OnSinkRemoved);
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Link Validation
|
||||||
|
/// <summary>
|
||||||
|
/// Removes invalid links where the saved sink doesn't exist/have a sink component for example
|
||||||
|
/// </summary>
|
||||||
|
private void OnSourceStartup(EntityUid sourceUid, DeviceLinkSourceComponent sourceComponent, ComponentStartup args)
|
||||||
|
{
|
||||||
|
List<EntityUid> invalidSinks = new();
|
||||||
|
foreach (var sinkUid in sourceComponent.LinkedPorts.Keys)
|
||||||
|
{
|
||||||
|
if (!TryComp<DeviceLinkSinkComponent?>(sinkUid, out var sinkComponent))
|
||||||
|
{
|
||||||
|
invalidSinks.Add(sinkUid);
|
||||||
|
foreach (var savedSinks in sourceComponent.Outputs.Values)
|
||||||
|
{
|
||||||
|
savedSinks.Remove(sinkUid);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sinkComponent.LinkedSources.Add(sourceUid);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var invalidSink in invalidSinks)
|
||||||
|
{
|
||||||
|
sourceComponent.LinkedPorts.Remove(invalidSink);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Same with <see cref="OnSourceStartup"/> but also checks that the saved ports are present on the sink
|
||||||
|
/// </summary>
|
||||||
|
private void OnSinkStartup(EntityUid sinkUid, DeviceLinkSinkComponent sinkComponent, ComponentStartup args)
|
||||||
|
{
|
||||||
|
List<EntityUid> invalidSources = new();
|
||||||
|
foreach (var sourceUid in sinkComponent.LinkedSources)
|
||||||
|
{
|
||||||
|
if (!TryComp<DeviceLinkSourceComponent>(sourceUid, out var sourceComponent))
|
||||||
|
{
|
||||||
|
invalidSources.Add(sourceUid);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sourceComponent.LinkedPorts.TryGetValue(sinkUid, out var linkedPorts))
|
||||||
|
{
|
||||||
|
foreach (var savedSinks in sourceComponent.Outputs.Values)
|
||||||
|
{
|
||||||
|
savedSinks.Remove(sinkUid);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sinkComponent.Ports == null)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
List<(string, string)> invalidLinks = new();
|
||||||
|
foreach (var link in linkedPorts)
|
||||||
|
{
|
||||||
|
if (!sinkComponent.Ports.Contains(link.sink) || !(sourceComponent.Outputs.GetValueOrDefault(link.source)?.Contains(sinkUid) ?? false))
|
||||||
|
invalidLinks.Add(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var invalidLink in invalidLinks)
|
||||||
|
{
|
||||||
|
linkedPorts.Remove(invalidLink);
|
||||||
|
sourceComponent.Outputs.GetValueOrDefault(invalidLink.Item1)?.Remove(sinkUid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var invalidSource in invalidSources)
|
||||||
|
{
|
||||||
|
sinkComponent.LinkedSources.Remove(invalidSource);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ensures that its links get deleted when a source gets removed
|
||||||
|
/// </summary>
|
||||||
|
private void OnSourceRemoved(EntityUid uid, DeviceLinkSourceComponent component, ComponentRemove args)
|
||||||
|
{
|
||||||
|
foreach (var sinkUid in component.LinkedPorts.Keys)
|
||||||
|
{
|
||||||
|
RemoveSinkFromSource(uid, sinkUid, component);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Ensures that its links get deleted when a sink gets removed
|
||||||
|
/// </summary>
|
||||||
|
private void OnSinkRemoved(EntityUid sinkUid, DeviceLinkSinkComponent sinkComponent, ComponentRemove args)
|
||||||
|
{
|
||||||
|
foreach (var linkedSource in sinkComponent.LinkedSources)
|
||||||
|
{
|
||||||
|
RemoveSinkFromSource(linkedSource, sinkUid, null, sinkComponent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#region Ports
|
||||||
|
/// <summary>
|
||||||
|
/// Convenience function to add several ports to an entity
|
||||||
|
/// </summary>
|
||||||
|
public void EnsureSourcePorts(EntityUid uid, params string[] ports)
|
||||||
|
{
|
||||||
|
var comp = EnsureComp<DeviceLinkSourceComponent>(uid);
|
||||||
|
comp.Ports ??= new HashSet<string>();
|
||||||
|
|
||||||
|
foreach (var port in ports)
|
||||||
|
{
|
||||||
|
comp.Ports?.Add(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convenience function to add several ports to an entity.
|
||||||
|
/// </summary>
|
||||||
|
public void EnsureSinkPorts(EntityUid uid, params string[] ports)
|
||||||
|
{
|
||||||
|
var comp = EnsureComp<DeviceLinkSinkComponent>(uid);
|
||||||
|
comp.Ports ??= new HashSet<string>();
|
||||||
|
|
||||||
|
foreach (var port in ports)
|
||||||
|
{
|
||||||
|
comp.Ports?.Add(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the available ports from a source
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A list of source port prototypes</returns>
|
||||||
|
public List<SourcePortPrototype> GetSourcePorts(EntityUid sourceUid, DeviceLinkSourceComponent? sourceComponent = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(sourceUid, ref sourceComponent) || sourceComponent.Ports == null)
|
||||||
|
return new List<SourcePortPrototype>();
|
||||||
|
|
||||||
|
var sourcePorts = new List<SourcePortPrototype>();
|
||||||
|
foreach (var port in sourceComponent.Ports)
|
||||||
|
{
|
||||||
|
sourcePorts.Add(_prototypeManager.Index<SourcePortPrototype>(port));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sourcePorts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Retrieves the available ports from a sink
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A list of sink port prototypes</returns>
|
||||||
|
public List<SinkPortPrototype> GetSinkPorts(EntityUid sinkUid, DeviceLinkSinkComponent? sinkComponent = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(sinkUid, ref sinkComponent) || sinkComponent.Ports == null)
|
||||||
|
return new List<SinkPortPrototype>();
|
||||||
|
|
||||||
|
var sinkPorts = new List<SinkPortPrototype>();
|
||||||
|
foreach (var port in sinkComponent.Ports)
|
||||||
|
{
|
||||||
|
sinkPorts.Add(_prototypeManager.Index<SinkPortPrototype>(port));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sinkPorts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convenience function to retrieve the name of a port prototype
|
||||||
|
/// </summary>
|
||||||
|
public string PortName<TPort>(string port) where TPort : DevicePortPrototype, IPrototype
|
||||||
|
{
|
||||||
|
if (!_prototypeManager.TryIndex<TPort>(port, out var proto))
|
||||||
|
return port;
|
||||||
|
|
||||||
|
return Loc.GetString(proto.Name);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Links
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the links of a source
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A list of sink and source port ids that are linked together</returns>
|
||||||
|
public HashSet<(string source, string sink)> GetLinks(EntityUid sourceUid, EntityUid sinkUid, DeviceLinkSourceComponent? sourceComponent = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(sourceUid, ref sourceComponent) || !sourceComponent.LinkedPorts.TryGetValue(sinkUid, out var links))
|
||||||
|
return new HashSet<(string source, string sink)>();
|
||||||
|
|
||||||
|
return links;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns the default links for the given list of source port prototypes
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sources">The list of source port prototypes to get the default links for</param>
|
||||||
|
/// <returns>A list of sink and source port ids</returns>
|
||||||
|
public List<(string source, string sink)> GetDefaults(List<SourcePortPrototype> sources)
|
||||||
|
{
|
||||||
|
var defaults = new List<(string, string)>();
|
||||||
|
foreach (var source in sources)
|
||||||
|
{
|
||||||
|
if (source.DefaultLinks == null)
|
||||||
|
return new List<(string, string)>();
|
||||||
|
|
||||||
|
foreach (var defaultLink in source.DefaultLinks)
|
||||||
|
{
|
||||||
|
defaults.Add((source.ID, defaultLink));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return defaults;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Links the given source and sink by their default links
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId">Optinal user uid for displaying popups</param>
|
||||||
|
/// <param name="sourceUid">The source uid</param>
|
||||||
|
/// <param name="sinkUid">The sink uid</param>
|
||||||
|
/// <param name="sourceComponent"></param>
|
||||||
|
/// <param name="sinkComponent"></param>
|
||||||
|
public void LinkDefaults(
|
||||||
|
EntityUid? userId,
|
||||||
|
EntityUid sourceUid,
|
||||||
|
EntityUid sinkUid,
|
||||||
|
DeviceLinkSourceComponent? sourceComponent = null,
|
||||||
|
DeviceLinkSinkComponent? sinkComponent = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(sourceUid, ref sourceComponent) || !Resolve(sinkUid, ref sinkComponent))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var sourcePorts = GetSourcePorts(sourceUid, sourceComponent);
|
||||||
|
var defaults = GetDefaults(sourcePorts);
|
||||||
|
SaveLinks(userId, sourceUid, sinkUid, defaults, sourceComponent, sinkComponent);
|
||||||
|
|
||||||
|
if (userId != null)
|
||||||
|
_popupSystem.PopupCursor(Loc.GetString("signal-linking-verb-success", ("machine", sourceUid)), userId.Value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Saves multiple links between a source and a sink device.
|
||||||
|
/// Ignores links where either the source or sink port aren't present
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="userId">Optinal user uid for displaying popups</param>
|
||||||
|
/// <param name="sourceUid">The source uid</param>
|
||||||
|
/// <param name="sinkUid">The sink uid</param>
|
||||||
|
/// <param name="links">List of source and sink ids to link</param>
|
||||||
|
/// <param name="sourceComponent"></param>
|
||||||
|
/// <param name="sinkComponent"></param>
|
||||||
|
public void SaveLinks(
|
||||||
|
EntityUid? userId,
|
||||||
|
EntityUid sourceUid,
|
||||||
|
EntityUid sinkUid,
|
||||||
|
List<(string source, string sink)> links,
|
||||||
|
DeviceLinkSourceComponent? sourceComponent = null,
|
||||||
|
DeviceLinkSinkComponent? sinkComponent = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(sourceUid, ref sourceComponent) || !Resolve(sinkUid, ref sinkComponent))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sourceComponent.Ports == null || sinkComponent.Ports == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!InRange(sourceUid, sinkUid, sourceComponent.Range))
|
||||||
|
{
|
||||||
|
if (userId != null)
|
||||||
|
_popupSystem.PopupCursor(Loc.GetString("signal-linker-component-out-of-range"), userId.Value);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
RemoveSinkFromSource(sourceUid, sinkUid, sourceComponent);
|
||||||
|
foreach (var (source, sink) in links)
|
||||||
|
{
|
||||||
|
if (!sourceComponent.Ports.Contains(source) || !sinkComponent.Ports.Contains(sink))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!CanLink(userId, sourceUid, sinkUid, source, sink, false, sourceComponent))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
sourceComponent.Outputs.GetOrNew(source).Add(sinkUid);
|
||||||
|
sourceComponent.LinkedPorts.GetOrNew(sinkUid).Add((source, sink));
|
||||||
|
|
||||||
|
SendNewLinkEvent(userId, sourceUid, source, sinkUid, sink);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (links.Count > 0)
|
||||||
|
sinkComponent.LinkedSources.Add(sourceUid);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Removes all links between a source and a sink
|
||||||
|
/// </summary>
|
||||||
|
public void RemoveSinkFromSource(
|
||||||
|
EntityUid sourceUid,
|
||||||
|
EntityUid sinkUid,
|
||||||
|
DeviceLinkSourceComponent? sourceComponent = null,
|
||||||
|
DeviceLinkSinkComponent? sinkComponent = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(sourceUid, ref sourceComponent, false) || !Resolve(sinkUid, ref sinkComponent, false))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (sourceComponent.LinkedPorts.TryGetValue(sinkUid, out var ports))
|
||||||
|
{
|
||||||
|
foreach (var (sourcePort, sinkPort) in ports)
|
||||||
|
{
|
||||||
|
RaiseLocalEvent(sourceUid, new PortDisconnectedEvent(sourcePort));
|
||||||
|
RaiseLocalEvent(sinkUid, new PortDisconnectedEvent(sinkPort));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sinkComponent.LinkedSources.Remove(sourceUid);
|
||||||
|
sourceComponent.LinkedPorts.Remove(sinkUid);
|
||||||
|
var outputLists = sourceComponent.Outputs.Values;
|
||||||
|
foreach (var outputList in outputLists)
|
||||||
|
{
|
||||||
|
outputList.Remove(sinkUid);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds or removes a link depending on if it's already present
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>True if the link was successfully added or removed</returns>
|
||||||
|
public bool ToggleLink(
|
||||||
|
EntityUid? userId,
|
||||||
|
EntityUid sourceUid,
|
||||||
|
EntityUid sinkUid,
|
||||||
|
string source,
|
||||||
|
string sink,
|
||||||
|
DeviceLinkSourceComponent? sourceComponent = null,
|
||||||
|
DeviceLinkSinkComponent? sinkComponent = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(sourceUid, ref sourceComponent) || !Resolve(sinkUid, ref sinkComponent))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (sourceComponent.Ports == null || sinkComponent.Ports == null)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var outputs = sourceComponent.Outputs.GetOrNew(source);
|
||||||
|
var linkedPorts = sourceComponent.LinkedPorts.GetOrNew(sinkUid);
|
||||||
|
|
||||||
|
if (linkedPorts.Contains((source, sink)))
|
||||||
|
{
|
||||||
|
RaiseLocalEvent(sourceUid, new PortDisconnectedEvent(source));
|
||||||
|
RaiseLocalEvent(sinkUid, new PortDisconnectedEvent(sink));
|
||||||
|
|
||||||
|
outputs.Remove(sinkUid);
|
||||||
|
linkedPorts.Remove((source, sink));
|
||||||
|
|
||||||
|
if (linkedPorts.Count != 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
sourceComponent.LinkedPorts.Remove(sinkUid);
|
||||||
|
sinkComponent.LinkedSources.Remove(sourceUid);
|
||||||
|
CreateLinkPopup(userId, sourceUid, source, sinkUid, sink, true);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (!sourceComponent.Ports.Contains(source) || !sinkComponent.Ports.Contains(sink))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!CanLink(userId, sourceUid, sinkUid, source, sink, true, sourceComponent))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
outputs.Add(sinkUid);
|
||||||
|
linkedPorts.Add((source, sink));
|
||||||
|
sinkComponent.LinkedSources.Add(sourceUid);
|
||||||
|
|
||||||
|
SendNewLinkEvent(userId, sourceUid, source, sinkUid, sink);
|
||||||
|
CreateLinkPopup(userId, sourceUid, source, sinkUid, sink, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if a source and a sink can be linked by allowing other systems to veto the link
|
||||||
|
/// and by optionally checking if they are in range of each other
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
private bool CanLink(
|
||||||
|
EntityUid? userId,
|
||||||
|
EntityUid sourceUid,
|
||||||
|
EntityUid sinkUid,
|
||||||
|
string source,
|
||||||
|
string sink,
|
||||||
|
bool checkRange = true,
|
||||||
|
DeviceLinkSourceComponent? sourceComponent = null)
|
||||||
|
{
|
||||||
|
if (!Resolve(sourceUid, ref sourceComponent))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (checkRange && !InRange(sourceUid, sinkUid, sourceComponent.Range))
|
||||||
|
{
|
||||||
|
if (userId.HasValue)
|
||||||
|
_popupSystem.PopupCursor(Loc.GetString("signal-linker-component-out-of-range"), userId.Value);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var linkAttemptEvent = new LinkAttemptEvent(userId, sourceUid, source, sinkUid, sink);
|
||||||
|
|
||||||
|
RaiseLocalEvent(sourceUid, linkAttemptEvent, true);
|
||||||
|
if (linkAttemptEvent.Cancelled && userId.HasValue)
|
||||||
|
{
|
||||||
|
_popupSystem.PopupCursor(Loc.GetString("signal-linker-component-connection-refused", ("machine", source)), userId.Value);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
RaiseLocalEvent(sinkUid, linkAttemptEvent, true);
|
||||||
|
if (linkAttemptEvent.Cancelled && userId.HasValue)
|
||||||
|
{
|
||||||
|
_popupSystem.PopupCursor(Loc.GetString("signal-linker-component-connection-refused", ("machine", source)), userId.Value);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !linkAttemptEvent.Cancelled;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool InRange(EntityUid sourceUid, EntityUid sinkUid, float range)
|
||||||
|
{
|
||||||
|
return Transform(sourceUid).MapPosition.InRange(Transform(sinkUid).MapPosition, range);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void SendNewLinkEvent(EntityUid? user, EntityUid sourceUid, string source, EntityUid sinkUid, string sink)
|
||||||
|
{
|
||||||
|
var newLinkEvent = new NewLinkEvent(user, sourceUid, source, sinkUid, sink);
|
||||||
|
RaiseLocalEvent(sourceUid, newLinkEvent);
|
||||||
|
RaiseLocalEvent(sinkUid, newLinkEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateLinkPopup(EntityUid? userId, EntityUid sourceUid, string source, EntityUid sinkUid, string sink, bool removed)
|
||||||
|
{
|
||||||
|
if (!userId.HasValue)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var locString = removed ? "signal-linker-component-unlinked-port" : "signal-linker-component-linked-port";
|
||||||
|
|
||||||
|
_popupSystem.PopupCursor(Loc.GetString(locString, ("machine1", sourceUid), ("port1", PortName<SourcePortPrototype>(source)),
|
||||||
|
("machine2", sinkUid), ("port2", PortName<SinkPortPrototype>(sink))), userId.Value, PopupType.Medium);
|
||||||
|
}
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.MachineLinking
|
namespace Content.Shared.DeviceLinking
|
||||||
{
|
{
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public enum TwoWayLeverVisuals : byte
|
public enum TwoWayLeverVisuals : byte
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.DeviceNetwork;
|
namespace Content.Shared.DeviceNetwork.Components;
|
||||||
|
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
[NetworkedComponent]
|
[NetworkedComponent]
|
||||||
|
|||||||
@@ -1,14 +1,24 @@
|
|||||||
|
using Content.Shared.DeviceLinking;
|
||||||
|
using Content.Shared.DeviceNetwork.Systems;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
|
|
||||||
namespace Content.Shared.DeviceNetwork;
|
namespace Content.Shared.DeviceNetwork.Components;
|
||||||
|
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
[NetworkedComponent]
|
[NetworkedComponent]
|
||||||
[Access(typeof(SharedNetworkConfiguratorSystem))]
|
[Access(typeof(SharedNetworkConfiguratorSystem))]
|
||||||
public sealed class NetworkConfiguratorComponent : Component
|
public sealed class NetworkConfiguratorComponent : Component
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Determines whether the configurator is in linking mode or list mode
|
||||||
|
/// </summary>
|
||||||
|
[DataField("linkModeActive")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public bool LinkModeActive = false;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The entity containing a <see cref="DeviceListComponent"/> this configurator is currently interacting with
|
/// The entity containing a <see cref="DeviceListComponent"/> this configurator is currently interacting with
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -16,22 +26,48 @@ public sealed class NetworkConfiguratorComponent : Component
|
|||||||
public EntityUid? ActiveDeviceList = null;
|
public EntityUid? ActiveDeviceList = null;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The list of devices stored in the configurator-
|
/// The entity containing a <see cref="DeviceLinkSourceComponent"/> or <see cref="DeviceLinkSinkComponent"/> this configurator is currently interacting with.<br/>
|
||||||
|
/// If this is set the configurator is in linking mode.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("activeDeviceLink")]
|
||||||
|
public EntityUid? ActiveDeviceLink = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The target device this configurator is currently linking with the <see cref="ActiveDeviceLink"/>
|
||||||
|
/// </summary>
|
||||||
|
[DataField("deviceLinkTarget")]
|
||||||
|
public EntityUid? DeviceLinkTarget = null;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The list of devices stored in the configurator
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("devices")]
|
[DataField("devices")]
|
||||||
public Dictionary<string, EntityUid> Devices = new();
|
public Dictionary<string, EntityUid> Devices = new();
|
||||||
|
|
||||||
|
[DataField("useDelay")]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public TimeSpan UseDelay = TimeSpan.FromSeconds(0.5);
|
||||||
|
|
||||||
|
[DataField("lastUseAttempt", customTypeSerializer:typeof(TimeOffsetSerializer))]
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public TimeSpan LastUseAttempt;
|
||||||
|
|
||||||
[DataField("soundNoAccess")]
|
[DataField("soundNoAccess")]
|
||||||
public SoundSpecifier SoundNoAccess = new SoundPathSpecifier("/Audio/Machines/custom_deny.ogg");
|
public SoundSpecifier SoundNoAccess = new SoundPathSpecifier("/Audio/Machines/custom_deny.ogg");
|
||||||
|
|
||||||
|
[DataField("soundSwitchMode")]
|
||||||
|
public SoundSpecifier SoundSwitchMode = new SoundPathSpecifier("/Audio/Machines/beep.ogg");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public sealed class NetworkConfiguratorComponentState : ComponentState
|
public sealed class NetworkConfiguratorComponentState : ComponentState
|
||||||
{
|
{
|
||||||
public readonly EntityUid? ActiveDeviceList;
|
public readonly EntityUid? ActiveDeviceList;
|
||||||
|
public readonly bool LinkModeActive;
|
||||||
|
|
||||||
public NetworkConfiguratorComponentState(EntityUid? activeDeviceList)
|
public NetworkConfiguratorComponentState(EntityUid? activeDeviceList, bool linkModeActive)
|
||||||
{
|
{
|
||||||
ActiveDeviceList = activeDeviceList;
|
ActiveDeviceList = activeDeviceList;
|
||||||
|
LinkModeActive = linkModeActive;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,8 @@ namespace Content.Shared.DeviceNetwork;
|
|||||||
public enum NetworkConfiguratorUiKey
|
public enum NetworkConfiguratorUiKey
|
||||||
{
|
{
|
||||||
List,
|
List,
|
||||||
Configure
|
Configure,
|
||||||
|
Link
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
@@ -52,3 +53,33 @@ public sealed class NetworkConfiguratorButtonPressedMessage : BoundUserInterface
|
|||||||
ButtonKey = buttonKey;
|
ButtonKey = buttonKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class NetworkConfiguratorClearLinksMessage : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class NetworkConfiguratorToggleLinkMessage : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
public readonly string Source;
|
||||||
|
public readonly string Sink;
|
||||||
|
|
||||||
|
public NetworkConfiguratorToggleLinkMessage(string source, string sink)
|
||||||
|
{
|
||||||
|
Source = source;
|
||||||
|
Sink = sink;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class NetworkConfiguratorLinksSaveMessage : BoundUserInterfaceMessage
|
||||||
|
{
|
||||||
|
public readonly List<(string source, string sink)> Links;
|
||||||
|
|
||||||
|
public NetworkConfiguratorLinksSaveMessage(List<(string source, string sink)> links)
|
||||||
|
{
|
||||||
|
Links = links;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Robust.Shared.Serialization;
|
using Content.Shared.DeviceLinking;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.DeviceNetwork;
|
namespace Content.Shared.DeviceNetwork;
|
||||||
|
|
||||||
@@ -23,3 +24,24 @@ public sealed class DeviceListUserInterfaceState : BoundUserInterfaceState
|
|||||||
DeviceList = deviceList;
|
DeviceList = deviceList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class DeviceLinkUserInterfaceState : BoundUserInterfaceState
|
||||||
|
{
|
||||||
|
public readonly List<SourcePortPrototype> Sources;
|
||||||
|
public readonly List<SinkPortPrototype> Sinks;
|
||||||
|
public readonly HashSet<(string source, string sink)> Links;
|
||||||
|
public readonly List<(string source, string sink)>? Defaults;
|
||||||
|
public readonly string SourceAddress;
|
||||||
|
public readonly string SinkAddress;
|
||||||
|
|
||||||
|
public DeviceLinkUserInterfaceState(List<SourcePortPrototype> sources, List<SinkPortPrototype> sinks, HashSet<(string source, string sink)> links, string sourceAddress, string sinkAddress, List<(string source, string sink)>? defaults = default)
|
||||||
|
{
|
||||||
|
Links = links;
|
||||||
|
SourceAddress = sourceAddress;
|
||||||
|
SinkAddress = sinkAddress;
|
||||||
|
Defaults = defaults;
|
||||||
|
Sources = sources;
|
||||||
|
Sinks = sinks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Shared.DeviceNetwork.Components;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
namespace Content.Shared.DeviceNetwork;
|
namespace Content.Shared.DeviceNetwork;
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
using Content.Shared.Actions;
|
using Content.Shared.Actions;
|
||||||
|
using Content.Shared.DeviceNetwork.Components;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
namespace Content.Shared.DeviceNetwork;
|
namespace Content.Shared.DeviceNetwork.Systems;
|
||||||
|
|
||||||
public abstract class SharedNetworkConfiguratorSystem : EntitySystem
|
public abstract class SharedNetworkConfiguratorSystem : EntitySystem
|
||||||
{
|
{
|
||||||
@@ -17,7 +18,7 @@ public abstract class SharedNetworkConfiguratorSystem : EntitySystem
|
|||||||
private void GetNetworkConfiguratorState(EntityUid uid, NetworkConfiguratorComponent comp,
|
private void GetNetworkConfiguratorState(EntityUid uid, NetworkConfiguratorComponent comp,
|
||||||
ref ComponentGetState args)
|
ref ComponentGetState args)
|
||||||
{
|
{
|
||||||
args.State = new NetworkConfiguratorComponentState(comp.ActiveDeviceList);
|
args.State = new NetworkConfiguratorComponentState(comp.ActiveDeviceList, comp.LinkModeActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleNetworkConfiguratorState(EntityUid uid, NetworkConfiguratorComponent comp,
|
private void HandleNetworkConfiguratorState(EntityUid uid, NetworkConfiguratorComponent comp,
|
||||||
@@ -29,9 +30,22 @@ public abstract class SharedNetworkConfiguratorSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
comp.ActiveDeviceList = state.ActiveDeviceList;
|
comp.ActiveDeviceList = state.ActiveDeviceList;
|
||||||
|
comp.LinkModeActive = state.LinkModeActive;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class ClearAllOverlaysEvent : InstantActionEvent
|
public sealed class ClearAllOverlaysEvent : InstantActionEvent
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum NetworkConfiguratorVisuals
|
||||||
|
{
|
||||||
|
Mode
|
||||||
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum NetworkConfiguratorLayers
|
||||||
|
{
|
||||||
|
ModeLight
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
namespace Content.Shared.MachineLinking.Events
|
|
||||||
{
|
|
||||||
public sealed class LinkAttemptEvent : CancellableEntityEventArgs
|
|
||||||
{
|
|
||||||
public readonly EntityUid Transmitter;
|
|
||||||
public readonly EntityUid Receiver;
|
|
||||||
public readonly EntityUid? User;
|
|
||||||
public readonly string TransmitterPort;
|
|
||||||
public readonly string ReceiverPort;
|
|
||||||
|
|
||||||
public LinkAttemptEvent(EntityUid? user, EntityUid transmitter, string transmitterPort, EntityUid receiver, string receiverPort)
|
|
||||||
{
|
|
||||||
User = user;
|
|
||||||
Transmitter = transmitter;
|
|
||||||
TransmitterPort = transmitterPort;
|
|
||||||
Receiver = receiver;
|
|
||||||
ReceiverPort = receiverPort;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
namespace Content.Shared.MachineLinking.Events
|
|
||||||
{
|
|
||||||
public sealed class NewLinkEvent : EntityEventArgs
|
|
||||||
{
|
|
||||||
public readonly EntityUid Transmitter;
|
|
||||||
public readonly EntityUid Receiver;
|
|
||||||
public readonly EntityUid? User;
|
|
||||||
public readonly string TransmitterPort;
|
|
||||||
public readonly string ReceiverPort;
|
|
||||||
|
|
||||||
public NewLinkEvent(EntityUid? user, EntityUid transmitter, string transmitterPort, EntityUid receiver, string receiverPort)
|
|
||||||
{
|
|
||||||
User = user;
|
|
||||||
Transmitter = transmitter;
|
|
||||||
TransmitterPort = transmitterPort;
|
|
||||||
Receiver = receiver;
|
|
||||||
ReceiverPort = receiverPort;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -26,4 +26,4 @@
|
|||||||
- files: ["vessel_warning.ogg"]
|
- files: ["vessel_warning.ogg"]
|
||||||
license: "CC-BY-4.0"
|
license: "CC-BY-4.0"
|
||||||
copyright: "Created by AUDACITIER (freesound), converted to MONO and .ogg and edited by EmoGarbage404 (github)."
|
copyright: "Created by AUDACITIER (freesound), converted to MONO and .ogg and edited by EmoGarbage404 (github)."
|
||||||
source: "https://freesound.org/people/AUDACITIER/sounds/629196/"
|
source: "https://freesound.org/people/AUDACITIER/sounds/629196/"
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ device-frequency-prototype-name-lights = Smart Lights
|
|||||||
device-frequency-prototype-name-mailing-units = Mailing Units
|
device-frequency-prototype-name-mailing-units = Mailing Units
|
||||||
device-frequency-prototype-name-pdas = PDAs
|
device-frequency-prototype-name-pdas = PDAs
|
||||||
device-frequency-prototype-name-fax = Fax
|
device-frequency-prototype-name-fax = Fax
|
||||||
|
device-frequency-prototype-name-basic-device = Basic Devices
|
||||||
|
|
||||||
## camera frequencies
|
## camera frequencies
|
||||||
device-frequency-prototype-name-surveillance-camera-test = Subnet Test
|
device-frequency-prototype-name-surveillance-camera-test = Subnet Test
|
||||||
|
|||||||
@@ -6,12 +6,23 @@ network-configurator-too-many-devices = Too many devices stored on this device!
|
|||||||
network-configurator-update-ok = Device storage updated.
|
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!
|
||||||
|
network-configurator-link-mode-started = Started linking device: {$device}
|
||||||
|
network-configurator-link-mode-stopped = Stopped linking.
|
||||||
|
network-configurator-mode-link = Link
|
||||||
|
network-configurator-mode-list = List
|
||||||
|
network-configurator-switched-mode = Switched mode to: {$mode}
|
||||||
|
|
||||||
# Verbs
|
# Verbs
|
||||||
network-configurator-save-device = Save device
|
network-configurator-save-device = Save device
|
||||||
network-configurator-configure = Configure
|
network-configurator-configure = Configure
|
||||||
|
network-configurator-switch-mode = Switch mode
|
||||||
|
network-configurator-link-defaults = Link defaults
|
||||||
|
network-configurator-start-link = Start link
|
||||||
|
network-configurator-link = Link
|
||||||
|
|
||||||
# ui
|
# ui
|
||||||
|
network-configurator-title-saved-devices = Saved Devices
|
||||||
|
network-configurator-title-device-configuration = Device Configuration
|
||||||
network-configurator-ui-clear-button = Clear
|
network-configurator-ui-clear-button = Clear
|
||||||
network-configurator-ui-count-label = {$count} Devices
|
network-configurator-ui-count-label = {$count} Devices
|
||||||
network-configurator-clear-network-link-overlays = Clear network link overlays
|
network-configurator-clear-network-link-overlays = Clear network link overlays
|
||||||
@@ -24,3 +35,13 @@ network-configurator-tooltip-edit = Edit targets device list
|
|||||||
network-configurator-tooltip-clear = Clear targets device list
|
network-configurator-tooltip-clear = Clear targets device list
|
||||||
network-configurator-tooltip-copy = Copy targets device list to multitool
|
network-configurator-tooltip-copy = Copy targets device list to multitool
|
||||||
network-configurator-tooltip-show = Show a holographic visualization of targets device list
|
network-configurator-tooltip-show = Show a holographic visualization of targets device list
|
||||||
|
|
||||||
|
# examine
|
||||||
|
network-configurator-examine-mode-link = [color=red]Link[/color]
|
||||||
|
network-configurator-examine-mode-list = [color=green]List[/color]
|
||||||
|
network-configurator-examine-current-mode = Current mode: {$mode}
|
||||||
|
network-configurator-examine-switch-modes = Press {$key} to switch modes
|
||||||
|
|
||||||
|
# item status
|
||||||
|
network-configurator-item-status-label = Current mode: {$mode}
|
||||||
|
{$keybinding} to switch mode
|
||||||
|
|||||||
@@ -4,6 +4,8 @@ guide-entry-atmospherics = Atmospherics
|
|||||||
guide-entry-botany = Botany
|
guide-entry-botany = Botany
|
||||||
guide-entry-fires = Fires & Space
|
guide-entry-fires = Fires & Space
|
||||||
guide-entry-shuttle-craft = Shuttle-craft
|
guide-entry-shuttle-craft = Shuttle-craft
|
||||||
|
guide-entry-networking = Networking
|
||||||
|
guide-entry-network-configurator = Network Configurator
|
||||||
guide-entry-power = Power
|
guide-entry-power = Power
|
||||||
guide-entry-ame = Antimatter Engine (AME)
|
guide-entry-ame = Antimatter Engine (AME)
|
||||||
guide-entry-singularity = Singularity
|
guide-entry-singularity = Singularity
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
signal-port-selector-menu-title = Port Selector
|
signal-port-selector-menu-title = Port Selector
|
||||||
signal-port-selector-menu-clear = Clear
|
signal-port-selector-menu-clear = Clear
|
||||||
signal-port-selector-menu-link-defaults = Link defaults
|
signal-port-selector-menu-link-defaults = Link defaults
|
||||||
|
signal-port-selector-help = Select the ports you want to link up
|
||||||
|
signal-port-selector-menu-done = Done
|
||||||
|
|||||||
@@ -1,3 +1,6 @@
|
|||||||
|
signal-port-name-toggle = Autoclose
|
||||||
|
signal-port-description-toggle = Toggles whether the device should automatically close.
|
||||||
|
|
||||||
signal-port-name-toggle = Toggle
|
signal-port-name-toggle = Toggle
|
||||||
signal-port-description-toggle = Toggles the state of a device.
|
signal-port-description-toggle = Toggles the state of a device.
|
||||||
|
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
- id: Wirecutter
|
- id: Wirecutter
|
||||||
- id: Welder
|
- id: Welder
|
||||||
- id: Multitool
|
- id: Multitool
|
||||||
|
- id: NetworkConfigurator
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: ClothingBeltChiefEngineerFilled
|
id: ClothingBeltChiefEngineerFilled
|
||||||
@@ -24,6 +25,7 @@
|
|||||||
- id: WelderExperimental
|
- id: WelderExperimental
|
||||||
- id: Multitool
|
- id: Multitool
|
||||||
- id: CableApcStack
|
- id: CableApcStack
|
||||||
|
- id: NetworkConfigurator
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: ClothingBeltSecurityFilled
|
id: ClothingBeltSecurityFilled
|
||||||
|
|||||||
@@ -86,3 +86,8 @@
|
|||||||
id: Fax
|
id: Fax
|
||||||
name: device-frequency-prototype-name-fax
|
name: device-frequency-prototype-name-fax
|
||||||
frequency: 2640
|
frequency: 2640
|
||||||
|
|
||||||
|
- type: deviceFrequency
|
||||||
|
id: BasicDevice
|
||||||
|
name: device-frequency-prototype-name-basic-device
|
||||||
|
frequency: 1280
|
||||||
|
|||||||
74
Resources/Prototypes/DeviceLinking/sink_ports.yml
Normal file
74
Resources/Prototypes/DeviceLinking/sink_ports.yml
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
- type: sinkPort
|
||||||
|
id: AutoClose
|
||||||
|
name: signal-port-name-autoclose
|
||||||
|
description: signal-port-description-autoclose
|
||||||
|
|
||||||
|
- type: sinkPort
|
||||||
|
id: Toggle
|
||||||
|
name: signal-port-name-toggle
|
||||||
|
description: signal-port-description-toggle
|
||||||
|
|
||||||
|
- type: sinkPort
|
||||||
|
id: On
|
||||||
|
name: signal-port-name-on-receiver
|
||||||
|
description: signal-port-description-on-receiver
|
||||||
|
|
||||||
|
- type: sinkPort
|
||||||
|
id: Off
|
||||||
|
name: signal-port-name-off-receiver
|
||||||
|
description: signal-port-description-off-receiver
|
||||||
|
|
||||||
|
- type: sinkPort
|
||||||
|
id: Forward
|
||||||
|
name: signal-port-name-forward
|
||||||
|
description: signal-port-description-forward
|
||||||
|
|
||||||
|
- type: sinkPort
|
||||||
|
id: Reverse
|
||||||
|
name: signal-port-name-reverse
|
||||||
|
description: signal-port-description-reverse
|
||||||
|
|
||||||
|
- type: sinkPort
|
||||||
|
id: Open
|
||||||
|
name: signal-port-name-open
|
||||||
|
description: signal-port-description-open
|
||||||
|
|
||||||
|
- type: sinkPort
|
||||||
|
id: Close
|
||||||
|
name: signal-port-name-close
|
||||||
|
description: signal-port-description-close
|
||||||
|
|
||||||
|
- type: sinkPort
|
||||||
|
id: Trigger
|
||||||
|
name: signal-port-name-trigger
|
||||||
|
description: signal-port-description-trigger
|
||||||
|
|
||||||
|
- type: sinkPort
|
||||||
|
id: OrderReceiver
|
||||||
|
name: signal-port-name-order-receiver
|
||||||
|
description: signal-port-description-order-receiver
|
||||||
|
|
||||||
|
- type: sinkPort
|
||||||
|
id: Pressurize
|
||||||
|
name: signal-port-name-pressurize
|
||||||
|
description: signal-port-description-pressurize
|
||||||
|
|
||||||
|
- type: sinkPort
|
||||||
|
id: Depressurize
|
||||||
|
name: signal-port-name-depressurize
|
||||||
|
description: signal-port-description-depressurize
|
||||||
|
|
||||||
|
- type: sinkPort
|
||||||
|
id: CloningPodReceiver
|
||||||
|
name: signal-port-name-pod-receiver
|
||||||
|
description: signal-port-description-pod-receiver
|
||||||
|
|
||||||
|
- type: sinkPort
|
||||||
|
id: MedicalScannerReceiver
|
||||||
|
name: signal-port-name-med-scanner-receiver
|
||||||
|
description: signal-port-description-med-scanner-receiver
|
||||||
|
|
||||||
|
- type: sinkPort
|
||||||
|
id: ArtifactAnalyzerReceiver
|
||||||
|
name: signal-port-name-artifact-analyzer-receiver
|
||||||
|
description: signal-port-description-artifact-analyzer-receiver
|
||||||
57
Resources/Prototypes/DeviceLinking/source_ports.yml
Normal file
57
Resources/Prototypes/DeviceLinking/source_ports.yml
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
- type: sourcePort
|
||||||
|
id: Pressed
|
||||||
|
name: signal-port-name-pressed
|
||||||
|
description: signal-port-description-pressed
|
||||||
|
defaultLinks: [ Toggle, Trigger ]
|
||||||
|
|
||||||
|
- type: sourcePort
|
||||||
|
id: On
|
||||||
|
name: signal-port-name-on-transmitter
|
||||||
|
description: signal-port-description-on-transmitter
|
||||||
|
defaultLinks: [ On, Open, Forward, Trigger ]
|
||||||
|
|
||||||
|
- type: sourcePort
|
||||||
|
id: Off
|
||||||
|
name: signal-port-name-off-transmitter
|
||||||
|
description: signal-port-description-off-transmitter
|
||||||
|
defaultLinks: [ Off, Close ]
|
||||||
|
|
||||||
|
- type: sourcePort
|
||||||
|
id: Left
|
||||||
|
name: signal-port-name-left
|
||||||
|
description: signal-port-description-left
|
||||||
|
defaultLinks: [ On, Open, Forward, Trigger ]
|
||||||
|
|
||||||
|
- type: sourcePort
|
||||||
|
id: Right
|
||||||
|
name: signal-port-name-right
|
||||||
|
description: signal-port-description-right
|
||||||
|
defaultLinks: [ On, Open, Reverse, Trigger ]
|
||||||
|
|
||||||
|
- type: sourcePort
|
||||||
|
id: Middle
|
||||||
|
name: signal-port-name-middle
|
||||||
|
description: signal-port-description-middle
|
||||||
|
defaultLinks: [ Off, Close ]
|
||||||
|
|
||||||
|
- type: sourcePort
|
||||||
|
id: OrderSender
|
||||||
|
name: signal-port-name-order-sender
|
||||||
|
description: signal-port-description-order-sender
|
||||||
|
defaultLinks: [ OrderReceiver ]
|
||||||
|
|
||||||
|
- type: sourcePort
|
||||||
|
id: CloningPodSender
|
||||||
|
name: signal-port-name-pod-receiver
|
||||||
|
description: signal-port-description-pod-sender
|
||||||
|
|
||||||
|
- type: sourcePort
|
||||||
|
id: MedicalScannerSender
|
||||||
|
name: signal-port-name-med-scanner-sender
|
||||||
|
description: signal-port-description-med-scanner-sender
|
||||||
|
|
||||||
|
- type: sourcePort
|
||||||
|
id: ArtifactAnalyzerSender
|
||||||
|
name: signal-port-name-artifact-analyzer-sender
|
||||||
|
description: signal-port-description-artifact-analyzer-sender
|
||||||
|
defaultLinks: [ ArtifactAnalyzerReceiver ]
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Belt/utility.rsi
|
sprite: Clothing/Belt/utility.rsi
|
||||||
- type: Storage
|
- type: Storage
|
||||||
|
capacity: 45
|
||||||
# TODO: Fill this out more.
|
# TODO: Fill this out more.
|
||||||
whitelist:
|
whitelist:
|
||||||
tags:
|
tags:
|
||||||
@@ -26,10 +27,11 @@
|
|||||||
- CigPack
|
- CigPack
|
||||||
- Radio
|
- Radio
|
||||||
- HolofanProjector
|
- HolofanProjector
|
||||||
|
- Multitool
|
||||||
- AppraisalTool
|
- AppraisalTool
|
||||||
components:
|
components:
|
||||||
- AirlockPainter
|
- AirlockPainter
|
||||||
- SignalLinker
|
- NetworkConfigurator
|
||||||
- RCD
|
- RCD
|
||||||
- RCDAmmo
|
- RCDAmmo
|
||||||
- Welder
|
- Welder
|
||||||
@@ -63,8 +65,8 @@
|
|||||||
- Wrench
|
- Wrench
|
||||||
multitool:
|
multitool:
|
||||||
whitelist:
|
whitelist:
|
||||||
components:
|
tags:
|
||||||
- SignalLinker
|
- Multitool
|
||||||
sprite: Clothing/Belt/belt_overlay.rsi
|
sprite: Clothing/Belt/belt_overlay.rsi
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
|
|
||||||
@@ -79,7 +81,7 @@
|
|||||||
- type: Clothing
|
- type: Clothing
|
||||||
sprite: Clothing/Belt/ce.rsi
|
sprite: Clothing/Belt/ce.rsi
|
||||||
- type: Storage
|
- type: Storage
|
||||||
capacity: 100
|
capacity: 105
|
||||||
# TODO: Fill this out more.
|
# TODO: Fill this out more.
|
||||||
whitelist:
|
whitelist:
|
||||||
tags:
|
tags:
|
||||||
@@ -96,10 +98,11 @@
|
|||||||
- CigPack
|
- CigPack
|
||||||
- Radio
|
- Radio
|
||||||
- HolofanProjector
|
- HolofanProjector
|
||||||
|
- Multitool
|
||||||
- AppraisalTool
|
- AppraisalTool
|
||||||
components:
|
components:
|
||||||
- AirlockPainter
|
- AirlockPainter
|
||||||
- SignalLinker
|
- NetworkConfigurator
|
||||||
- RCD
|
- RCD
|
||||||
- RCDAmmo
|
- RCDAmmo
|
||||||
- Welder
|
- Welder
|
||||||
@@ -135,8 +138,8 @@
|
|||||||
- Screwdriver
|
- Screwdriver
|
||||||
multitool:
|
multitool:
|
||||||
whitelist:
|
whitelist:
|
||||||
components:
|
tags:
|
||||||
- SignalLinker
|
- Multitool
|
||||||
wrench:
|
wrench:
|
||||||
whitelist:
|
whitelist:
|
||||||
tags:
|
tags:
|
||||||
|
|||||||
@@ -13,9 +13,9 @@
|
|||||||
- type: UseDelay
|
- type: UseDelay
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 40
|
price: 40
|
||||||
- type: SignalTransmitter
|
- type: DeviceLinkSource
|
||||||
outputs:
|
ports:
|
||||||
Pressed: []
|
- Pressed
|
||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- Payload
|
- Payload
|
||||||
|
|||||||
@@ -42,7 +42,12 @@
|
|||||||
- type: PayloadTrigger
|
- type: PayloadTrigger
|
||||||
components:
|
components:
|
||||||
- type: TriggerOnSignal
|
- type: TriggerOnSignal
|
||||||
- type: SignalReceiver
|
- type: DeviceNetwork
|
||||||
|
deviceNetId: Wireless
|
||||||
|
receiveFrequencyId: BasicDevice
|
||||||
|
- type: WirelessNetworkConnection
|
||||||
|
range: 200
|
||||||
|
- type: DeviceLinkSink
|
||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 40
|
price: 40
|
||||||
|
|
||||||
|
|||||||
@@ -108,7 +108,9 @@
|
|||||||
- type: Tool
|
- type: Tool
|
||||||
qualities:
|
qualities:
|
||||||
- Pulsing
|
- Pulsing
|
||||||
- type: SignalLinker
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- Multitool
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: cowelding tool
|
name: cowelding tool
|
||||||
|
|||||||
@@ -196,21 +196,9 @@
|
|||||||
- type: Tool
|
- type: Tool
|
||||||
qualities:
|
qualities:
|
||||||
- Pulsing
|
- Pulsing
|
||||||
- type: SignalLinker
|
|
||||||
- type: NetworkConfigurator
|
|
||||||
- type: ActivatableUI
|
|
||||||
key: enum.NetworkConfiguratorUiKey.List
|
|
||||||
inHandsOnly: true
|
|
||||||
- type: UserInterface
|
|
||||||
interfaces:
|
|
||||||
- key: enum.SignalLinkerUiKey.Key
|
|
||||||
type: SignalPortSelectorBoundUserInterface
|
|
||||||
- key: enum.NetworkConfiguratorUiKey.List
|
|
||||||
type: NetworkConfiguratorBoundUserInterface
|
|
||||||
- key: enum.NetworkConfiguratorUiKey.Configure
|
|
||||||
type: NetworkConfiguratorBoundUserInterface
|
|
||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
|
- Multitool
|
||||||
- DroneUsable
|
- DroneUsable
|
||||||
- type: PhysicalComposition
|
- type: PhysicalComposition
|
||||||
materialComposition:
|
materialComposition:
|
||||||
@@ -219,6 +207,54 @@
|
|||||||
- type: StaticPrice
|
- type: StaticPrice
|
||||||
price: 60
|
price: 60
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
name: network configurator
|
||||||
|
parent: BaseItem
|
||||||
|
id: NetworkConfigurator
|
||||||
|
description: A tool for linking devices together. Has two modes, a list mode for mass linking devices and a linking mode for advanced device linking.
|
||||||
|
components:
|
||||||
|
- type: EmitSoundOnLand
|
||||||
|
sound:
|
||||||
|
path: /Audio/Items/multitool_drop.ogg
|
||||||
|
- type: Sprite
|
||||||
|
sprite: Objects/Tools/network_configurator.rsi
|
||||||
|
layers:
|
||||||
|
- state: icon
|
||||||
|
- state: mode-list
|
||||||
|
map: ["enum.NetworkConfiguratorLayers.ModeLight"]
|
||||||
|
shader: unshaded
|
||||||
|
- type: Item
|
||||||
|
size: 5
|
||||||
|
- type: Clothing
|
||||||
|
sprite: Objects/Tools/network_configurator.rsi
|
||||||
|
quickEquip: false
|
||||||
|
slots:
|
||||||
|
- Belt
|
||||||
|
- type: Appearance
|
||||||
|
- type: GenericVisualizer
|
||||||
|
visuals:
|
||||||
|
enum.NetworkConfiguratorVisuals.Mode:
|
||||||
|
enum.NetworkConfiguratorLayers.ModeLight:
|
||||||
|
True: { state: mode-link }
|
||||||
|
False: { state: mode-list }
|
||||||
|
- type: NetworkConfigurator
|
||||||
|
- type: ActivatableUI
|
||||||
|
key: enum.NetworkConfiguratorUiKey.List
|
||||||
|
inHandsOnly: true
|
||||||
|
- type: UserInterface
|
||||||
|
interfaces:
|
||||||
|
- key: enum.NetworkConfiguratorUiKey.List
|
||||||
|
type: NetworkConfiguratorBoundUserInterface
|
||||||
|
- key: enum.NetworkConfiguratorUiKey.Configure
|
||||||
|
type: NetworkConfiguratorBoundUserInterface
|
||||||
|
- key: enum.NetworkConfiguratorUiKey.Link
|
||||||
|
type: NetworkConfiguratorBoundUserInterface
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- DroneUsable
|
||||||
|
- type: StaticPrice
|
||||||
|
price: 60
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: power drill
|
name: power drill
|
||||||
parent: BaseItem
|
parent: BaseItem
|
||||||
@@ -371,13 +407,10 @@
|
|||||||
- type: Item
|
- type: Item
|
||||||
sprite: Objects/Tools/omnitool.rsi
|
sprite: Objects/Tools/omnitool.rsi
|
||||||
size: 20
|
size: 20
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- Multitool
|
||||||
- type: TilePrying
|
- type: TilePrying
|
||||||
- type: SignalLinker
|
|
||||||
requiredQuality: Pulsing
|
|
||||||
- type: UserInterface
|
|
||||||
interfaces:
|
|
||||||
- key: enum.SignalLinkerUiKey.Key
|
|
||||||
type: SignalPortSelectorBoundUserInterface
|
|
||||||
- type: Tool
|
- type: Tool
|
||||||
qualities:
|
qualities:
|
||||||
- Screwing
|
- Screwing
|
||||||
|
|||||||
@@ -18,9 +18,9 @@
|
|||||||
startOnStick: true
|
startOnStick: true
|
||||||
canToggleStartOnStick: true
|
canToggleStartOnStick: true
|
||||||
- type: TriggerOnSignal
|
- type: TriggerOnSignal
|
||||||
- type: SignalReceiver
|
- type: DeviceLinkSink
|
||||||
inputs:
|
ports:
|
||||||
Trigger: []
|
- Trigger
|
||||||
- type: Sticky
|
- type: Sticky
|
||||||
stickDelay: 5
|
stickDelay: 5
|
||||||
unstickDelay: 5
|
unstickDelay: 5
|
||||||
|
|||||||
@@ -78,12 +78,17 @@
|
|||||||
BoardName: "Airlock Control"
|
BoardName: "Airlock Control"
|
||||||
LayoutId: Airlock
|
LayoutId: Airlock
|
||||||
- type: DoorSignalControl
|
- type: DoorSignalControl
|
||||||
- type: SignalReceiver
|
- type: DeviceNetwork
|
||||||
inputs:
|
deviceNetId: Wireless
|
||||||
Open: []
|
receiveFrequencyId: BasicDevice
|
||||||
Close: []
|
- type: WirelessNetworkConnection
|
||||||
Toggle: []
|
range: 200
|
||||||
AutoClose: []
|
- type: DeviceLinkSink
|
||||||
|
ports:
|
||||||
|
- Open
|
||||||
|
- Close
|
||||||
|
- Toggle
|
||||||
|
- AutoClose
|
||||||
- type: UserInterface
|
- type: UserInterface
|
||||||
interfaces:
|
interfaces:
|
||||||
- key: enum.WiresUiKey.Key
|
- key: enum.WiresUiKey.Key
|
||||||
|
|||||||
@@ -76,11 +76,16 @@
|
|||||||
key: walls
|
key: walls
|
||||||
mode: NoSprite
|
mode: NoSprite
|
||||||
- type: DoorSignalControl
|
- type: DoorSignalControl
|
||||||
- type: SignalReceiver
|
- type: DeviceNetwork
|
||||||
inputs:
|
deviceNetId: Wireless
|
||||||
Open: []
|
receiveFrequencyId: BasicDevice
|
||||||
Close: []
|
- type: WirelessNetworkConnection
|
||||||
Toggle: []
|
range: 200
|
||||||
|
- type: DeviceLinkSink
|
||||||
|
ports:
|
||||||
|
- Open
|
||||||
|
- Close
|
||||||
|
- Toggle
|
||||||
- type: InteractionPopup
|
- type: InteractionPopup
|
||||||
interactSuccessString: comp-window-knock
|
interactSuccessString: comp-window-knock
|
||||||
messagePerceivedByOthers: comp-window-knock
|
messagePerceivedByOthers: comp-window-knock
|
||||||
|
|||||||
@@ -46,12 +46,17 @@
|
|||||||
- type: ApcPowerReceiver
|
- type: ApcPowerReceiver
|
||||||
- type: ExtensionCableReceiver
|
- type: ExtensionCableReceiver
|
||||||
- type: DoorSignalControl
|
- type: DoorSignalControl
|
||||||
- type: SignalReceiver
|
- type: DeviceNetwork
|
||||||
inputs:
|
deviceNetId: Wireless
|
||||||
Open: []
|
receiveFrequencyId: BasicDevice
|
||||||
Close: []
|
- type: WirelessNetworkConnection
|
||||||
Toggle: []
|
range: 200
|
||||||
AutoClose: []
|
- type: DeviceLinkSink
|
||||||
|
ports:
|
||||||
|
- Open
|
||||||
|
- Close
|
||||||
|
- Toggle
|
||||||
|
- AutoClose
|
||||||
- type: Damageable
|
- type: Damageable
|
||||||
damageContainer: Inorganic
|
damageContainer: Inorganic
|
||||||
damageModifierSet: Glass
|
damageModifierSet: Glass
|
||||||
|
|||||||
@@ -86,18 +86,19 @@
|
|||||||
- type: ApcPowerReceiver
|
- type: ApcPowerReceiver
|
||||||
- type: ExtensionCableReceiver
|
- type: ExtensionCableReceiver
|
||||||
- type: DeviceNetwork
|
- type: DeviceNetwork
|
||||||
deviceNetId: Apc
|
deviceNetId: Wireless
|
||||||
receiveFrequencyId: SmartLight
|
receiveFrequencyId: SmartLight
|
||||||
- type: ApcNetworkConnection
|
- type: WirelessNetworkConnection
|
||||||
|
range: 200
|
||||||
|
- type: DeviceLinkSink
|
||||||
|
ports:
|
||||||
|
- On
|
||||||
|
- Off
|
||||||
|
- Toggle
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
- type: PoweredLightVisuals
|
- type: PoweredLightVisuals
|
||||||
blinkingSound:
|
blinkingSound:
|
||||||
path: "/Audio/Machines/light_tube_on.ogg"
|
path: "/Audio/Machines/light_tube_on.ogg"
|
||||||
- type: SignalReceiver
|
|
||||||
inputs:
|
|
||||||
On: []
|
|
||||||
Off: []
|
|
||||||
Toggle: []
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: Poweredlight
|
id: Poweredlight
|
||||||
@@ -266,16 +267,17 @@
|
|||||||
- type: ApcPowerReceiver
|
- type: ApcPowerReceiver
|
||||||
- type: ExtensionCableReceiver
|
- type: ExtensionCableReceiver
|
||||||
- type: DeviceNetwork
|
- type: DeviceNetwork
|
||||||
deviceNetId: Apc
|
deviceNetId: Wireless
|
||||||
receiveFrequencyId: SmartLight
|
receiveFrequencyId: SmartLight
|
||||||
- type: ApcNetworkConnection
|
- type: WirelessNetworkConnection
|
||||||
|
range: 200
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
- type: PoweredLightVisuals
|
- type: PoweredLightVisuals
|
||||||
- type: SignalReceiver
|
- type: DeviceLinkSink
|
||||||
inputs:
|
ports:
|
||||||
On: []
|
- On
|
||||||
Off: []
|
- Off
|
||||||
Toggle: []
|
- Toggle
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: PoweredSmallLight
|
id: PoweredSmallLight
|
||||||
|
|||||||
@@ -91,9 +91,15 @@
|
|||||||
- type: ApcPowerReceiver
|
- type: ApcPowerReceiver
|
||||||
- type: ExtensionCableReceiver
|
- type: ExtensionCableReceiver
|
||||||
- type: DeviceNetwork
|
- type: DeviceNetwork
|
||||||
deviceNetId: Apc
|
deviceNetId: Wireless
|
||||||
receiveFrequencyId: SmartLight
|
receiveFrequencyId: SmartLight
|
||||||
- type: ApcNetworkConnection
|
- type: WirelessNetworkConnection
|
||||||
|
range: 200
|
||||||
|
- type: DeviceLinkSink
|
||||||
|
ports:
|
||||||
|
- On
|
||||||
|
- Off
|
||||||
|
- Toggle
|
||||||
- type: Construction
|
- type: Construction
|
||||||
graph: LightFixture
|
graph: LightFixture
|
||||||
node: groundLight
|
node: groundLight
|
||||||
@@ -101,11 +107,6 @@
|
|||||||
- type: PoweredLightVisuals
|
- type: PoweredLightVisuals
|
||||||
blinkingSound:
|
blinkingSound:
|
||||||
path: "/Audio/Machines/light_tube_on.ogg"
|
path: "/Audio/Machines/light_tube_on.ogg"
|
||||||
- type: SignalReceiver
|
|
||||||
inputs:
|
|
||||||
On: []
|
|
||||||
Off: []
|
|
||||||
Toggle: []
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: PoweredLightPostSmall
|
id: PoweredLightPostSmall
|
||||||
|
|||||||
@@ -378,10 +378,10 @@
|
|||||||
- type: DeviceList
|
- type: DeviceList
|
||||||
- type: DeviceNetwork
|
- type: DeviceNetwork
|
||||||
deviceNetId: Wired
|
deviceNetId: Wired
|
||||||
- type: SignalTransmitter
|
- type: DeviceLinkSource
|
||||||
transmissionRange: 5
|
range: 5
|
||||||
outputs:
|
ports:
|
||||||
ArtifactAnalyzerSender: []
|
- ArtifactAnalyzerSender
|
||||||
- type: ActivatableUI
|
- type: ActivatableUI
|
||||||
key: enum.ArtifactAnalzyerUiKey.Key
|
key: enum.ArtifactAnalzyerUiKey.Key
|
||||||
- type: UserInterface
|
- type: UserInterface
|
||||||
@@ -698,11 +698,11 @@
|
|||||||
radius: 1.5
|
radius: 1.5
|
||||||
energy: 1.6
|
energy: 1.6
|
||||||
color: "#1f8c28"
|
color: "#1f8c28"
|
||||||
- type: SignalTransmitter
|
- type: DeviceLinkSource
|
||||||
transmissionRange: 4
|
range: 4
|
||||||
outputs:
|
ports:
|
||||||
MedicalScannerSender: []
|
- MedicalScannerSender
|
||||||
CloningPodSender: []
|
- CloningPodSender
|
||||||
- type: ActivatableUI
|
- type: ActivatableUI
|
||||||
key: enum.CloningConsoleUiKey.Key
|
key: enum.CloningConsoleUiKey.Key
|
||||||
- type: UserInterface
|
- type: UserInterface
|
||||||
|
|||||||
@@ -49,10 +49,11 @@
|
|||||||
- type: ArtifactAnalyzer
|
- type: ArtifactAnalyzer
|
||||||
- type: DeviceNetwork
|
- type: DeviceNetwork
|
||||||
deviceNetId: Wired
|
deviceNetId: Wired
|
||||||
|
receiveFrequencyId: BasicDevice
|
||||||
- type: DeviceList
|
- type: DeviceList
|
||||||
- type: SignalReceiver
|
- type: DeviceLinkSink
|
||||||
inputs:
|
ports:
|
||||||
ArtifactAnalyzerReceiver: []
|
- ArtifactAnalyzerReceiver
|
||||||
- type: Machine
|
- type: Machine
|
||||||
board: ArtifactAnalyzerMachineCircuitboard
|
board: ArtifactAnalyzerMachineCircuitboard
|
||||||
- type: PointLight
|
- type: PointLight
|
||||||
|
|||||||
@@ -8,6 +8,10 @@
|
|||||||
- type: DeviceList
|
- type: DeviceList
|
||||||
- type: DeviceNetwork
|
- type: DeviceNetwork
|
||||||
deviceNetId: Wired
|
deviceNetId: Wired
|
||||||
|
receiveFrequencyId: BasicDevice
|
||||||
|
- type: DeviceLinkSink
|
||||||
|
ports:
|
||||||
|
- CloningPodReceiver
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
netsync: false
|
netsync: false
|
||||||
sprite: Structures/Machines/cloning.rsi
|
sprite: Structures/Machines/cloning.rsi
|
||||||
@@ -34,9 +38,6 @@
|
|||||||
- machine_board
|
- machine_board
|
||||||
- machine_parts
|
- machine_parts
|
||||||
- clonepod-bodyContainer
|
- clonepod-bodyContainer
|
||||||
- type: SignalReceiver
|
|
||||||
inputs:
|
|
||||||
CloningPodReceiver: []
|
|
||||||
- type: EmptyOnMachineDeconstruct
|
- type: EmptyOnMachineDeconstruct
|
||||||
containers:
|
containers:
|
||||||
- clonepod-bodyContainer
|
- clonepod-bodyContainer
|
||||||
|
|||||||
@@ -74,6 +74,7 @@
|
|||||||
- Wrench
|
- Wrench
|
||||||
- Crowbar
|
- Crowbar
|
||||||
- Multitool
|
- Multitool
|
||||||
|
- NetworkConfigurator
|
||||||
- AirlockPainter
|
- AirlockPainter
|
||||||
- CableStack
|
- CableStack
|
||||||
- HandheldGPSBasic
|
- HandheldGPSBasic
|
||||||
|
|||||||
@@ -7,7 +7,11 @@
|
|||||||
- type: MedicalScanner
|
- type: MedicalScanner
|
||||||
- type: DeviceNetwork
|
- type: DeviceNetwork
|
||||||
deviceNetId: Wired
|
deviceNetId: Wired
|
||||||
|
receiveFrequencyId: BasicDevice
|
||||||
- type: DeviceList
|
- type: DeviceList
|
||||||
|
- type: DeviceLinkSink
|
||||||
|
ports:
|
||||||
|
- MedicalScannerReceiver
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
netsync: false
|
netsync: false
|
||||||
sprite: Structures/Machines/scanner.rsi
|
sprite: Structures/Machines/scanner.rsi
|
||||||
@@ -58,9 +62,6 @@
|
|||||||
scanner-bodyContainer: !type:ContainerSlot
|
scanner-bodyContainer: !type:ContainerSlot
|
||||||
machine_board: !type:Container
|
machine_board: !type:Container
|
||||||
machine_parts: !type:Container
|
machine_parts: !type:Container
|
||||||
- type: SignalReceiver
|
|
||||||
inputs:
|
|
||||||
MedicalScannerReceiver: []
|
|
||||||
- type: Damageable
|
- type: Damageable
|
||||||
damageContainer: Inorganic
|
damageContainer: Inorganic
|
||||||
damageModifierSet: StrongMetallic
|
damageModifierSet: StrongMetallic
|
||||||
|
|||||||
@@ -42,11 +42,11 @@
|
|||||||
- MidImpassable
|
- MidImpassable
|
||||||
- LowImpassable
|
- LowImpassable
|
||||||
hard: False
|
hard: False
|
||||||
- type: SignalReceiver
|
- type: DeviceLinkSink
|
||||||
inputs:
|
ports:
|
||||||
Reverse: []
|
- Reverse
|
||||||
Forward: []
|
- Forward
|
||||||
Off: []
|
- Off
|
||||||
- type: Transform
|
- type: Transform
|
||||||
anchored: true
|
anchored: true
|
||||||
noRot: false
|
noRot: false
|
||||||
|
|||||||
@@ -208,11 +208,16 @@
|
|||||||
- type: PipeColorVisuals
|
- type: PipeColorVisuals
|
||||||
- type: GasValve
|
- type: GasValve
|
||||||
- type: SignalControlledValve
|
- type: SignalControlledValve
|
||||||
- type: SignalReceiver
|
- type: DeviceNetwork
|
||||||
inputs:
|
deviceNetId: Wireless
|
||||||
Open: []
|
receiveFrequencyId: BasicDevice
|
||||||
Close: []
|
- type: WirelessNetworkConnection
|
||||||
Toggle: []
|
range: 200
|
||||||
|
- type: DeviceLinkSink
|
||||||
|
ports:
|
||||||
|
- Open
|
||||||
|
- Close
|
||||||
|
- Toggle
|
||||||
- type: NodeContainer
|
- type: NodeContainer
|
||||||
nodes:
|
nodes:
|
||||||
inlet:
|
inlet:
|
||||||
@@ -296,10 +301,15 @@
|
|||||||
inlet: inlet
|
inlet: inlet
|
||||||
outlet: outlet
|
outlet: outlet
|
||||||
canLink: true
|
canLink: true
|
||||||
- type: SignalReceiver
|
- type: DeviceNetwork
|
||||||
inputs:
|
deviceNetId: Wireless
|
||||||
Pressurize: []
|
receiveFrequencyId: BasicDevice
|
||||||
Depressurize: []
|
- type: WirelessNetworkConnection
|
||||||
|
range: 200
|
||||||
|
- type: DeviceLinkSink
|
||||||
|
ports:
|
||||||
|
- Pressurize
|
||||||
|
- Depressurize
|
||||||
- type: Construction
|
- type: Construction
|
||||||
graph: GasBinary
|
graph: GasBinary
|
||||||
node: dualportventpump
|
node: dualportventpump
|
||||||
|
|||||||
@@ -24,10 +24,14 @@
|
|||||||
graph: SignalSwitchGraph
|
graph: SignalSwitchGraph
|
||||||
node: SignalSwitchNode
|
node: SignalSwitchNode
|
||||||
- type: Fixtures
|
- type: Fixtures
|
||||||
- type: SignalTransmitter
|
- type: DeviceNetwork
|
||||||
outputs:
|
deviceNetId: Wireless
|
||||||
On: []
|
- type: WirelessNetworkConnection
|
||||||
Off: []
|
range: 200
|
||||||
|
- type: DeviceLinkSource
|
||||||
|
ports:
|
||||||
|
- On
|
||||||
|
- Off
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: SignalButton
|
id: SignalButton
|
||||||
@@ -57,9 +61,13 @@
|
|||||||
graph: SignalButtonGraph
|
graph: SignalButtonGraph
|
||||||
node: SignalButtonNode
|
node: SignalButtonNode
|
||||||
- type: Fixtures
|
- type: Fixtures
|
||||||
- type: SignalTransmitter
|
- type: DeviceNetwork
|
||||||
outputs:
|
deviceNetId: Wireless
|
||||||
Pressed: []
|
- type: WirelessNetworkConnection
|
||||||
|
range: 200
|
||||||
|
- type: DeviceLinkSource
|
||||||
|
ports:
|
||||||
|
- Pressed
|
||||||
- type: Damageable
|
- type: Damageable
|
||||||
damageContainer: Inorganic
|
damageContainer: Inorganic
|
||||||
damageModifierSet: Metallic
|
damageModifierSet: Metallic
|
||||||
@@ -153,8 +161,12 @@
|
|||||||
- type: Construction
|
- type: Construction
|
||||||
graph: LeverGraph
|
graph: LeverGraph
|
||||||
node: LeverNode
|
node: LeverNode
|
||||||
- type: SignalTransmitter
|
- type: DeviceNetwork
|
||||||
outputs:
|
deviceNetId: Wireless
|
||||||
Left: []
|
- type: WirelessNetworkConnection
|
||||||
Right: []
|
range: 200
|
||||||
Middle: []
|
- type: DeviceLinkSource
|
||||||
|
ports:
|
||||||
|
- Left
|
||||||
|
- Right
|
||||||
|
- Middle
|
||||||
|
|||||||
@@ -32,9 +32,14 @@
|
|||||||
- type: Damageable
|
- type: Damageable
|
||||||
damageContainer: Inorganic
|
damageContainer: Inorganic
|
||||||
damageModifierSet: Metallic
|
damageModifierSet: Metallic
|
||||||
- type: SignalReceiver
|
- type: DeviceNetwork
|
||||||
inputs:
|
deviceNetId: Wireless
|
||||||
OrderReceiver: []
|
receiveFrequencyId: BasicDevice
|
||||||
|
- type: WirelessNetworkConnection
|
||||||
|
range: 200
|
||||||
|
- type: DeviceLinkSink
|
||||||
|
ports:
|
||||||
|
- OrderReceiver
|
||||||
- type: Destructible
|
- type: Destructible
|
||||||
thresholds:
|
thresholds:
|
||||||
- trigger:
|
- trigger:
|
||||||
|
|||||||
@@ -35,11 +35,11 @@
|
|||||||
- LowImpassable
|
- LowImpassable
|
||||||
hard: False
|
hard: False
|
||||||
- type: Conveyor
|
- type: Conveyor
|
||||||
- type: SignalReceiver
|
- type: DeviceLinkSink
|
||||||
inputs:
|
ports:
|
||||||
Reverse: []
|
- Reverse
|
||||||
Forward: []
|
- Forward
|
||||||
Off: []
|
- Off
|
||||||
- type: Appearance
|
- type: Appearance
|
||||||
- type: GenericVisualizer
|
- type: GenericVisualizer
|
||||||
visuals:
|
visuals:
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
- Construction
|
- Construction
|
||||||
- Power
|
- Power
|
||||||
- ShuttleCraft
|
- ShuttleCraft
|
||||||
|
- Networking
|
||||||
|
|
||||||
- type: guideEntry
|
- type: guideEntry
|
||||||
id: Construction
|
id: Construction
|
||||||
@@ -30,6 +31,19 @@
|
|||||||
name: guide-entry-shuttle-craft
|
name: guide-entry-shuttle-craft
|
||||||
text: "/ServerInfo/Guidebook/Shuttlecraft.xml"
|
text: "/ServerInfo/Guidebook/Shuttlecraft.xml"
|
||||||
|
|
||||||
|
- type: guideEntry
|
||||||
|
id: Networking
|
||||||
|
name: guide-entry-networking
|
||||||
|
text: "/ServerInfo/Guidebook/Networking.xml"
|
||||||
|
children:
|
||||||
|
- NetworkConfigurator
|
||||||
|
|
||||||
|
- type: guideEntry
|
||||||
|
id: NetworkConfigurator
|
||||||
|
name: guide-entry-network-configurator
|
||||||
|
text: "/ServerInfo/Guidebook/Network_Configurator.xml"
|
||||||
|
|
||||||
|
|
||||||
- type: guideEntry
|
- type: guideEntry
|
||||||
id: Power
|
id: Power
|
||||||
name: guide-entry-power
|
name: guide-entry-power
|
||||||
|
|||||||
@@ -86,6 +86,14 @@
|
|||||||
Steel: 200
|
Steel: 200
|
||||||
Plastic: 200
|
Plastic: 200
|
||||||
|
|
||||||
|
- type: latheRecipe
|
||||||
|
id: NetworkConfigurator
|
||||||
|
result: NetworkConfigurator
|
||||||
|
completetime: 2
|
||||||
|
materials:
|
||||||
|
Steel: 200
|
||||||
|
Plastic: 200
|
||||||
|
|
||||||
- type: latheRecipe
|
- type: latheRecipe
|
||||||
id: PowerDrill
|
id: PowerDrill
|
||||||
result: PowerDrill
|
result: PowerDrill
|
||||||
|
|||||||
@@ -194,8 +194,6 @@
|
|||||||
- Item
|
- Item
|
||||||
permanentComponents:
|
permanentComponents:
|
||||||
- type: TilePrying
|
- type: TilePrying
|
||||||
- type: SignalLinker
|
|
||||||
requiredQuality: Pulsing
|
|
||||||
- type: UserInterface
|
- type: UserInterface
|
||||||
interfaces:
|
interfaces:
|
||||||
- key: enum.SignalLinkerUiKey.Key
|
- key: enum.SignalLinkerUiKey.Key
|
||||||
@@ -206,6 +204,9 @@
|
|||||||
- Screwing
|
- Screwing
|
||||||
speed: 2 # Very powerful multitool to balance out the desire to sell or scrap for points
|
speed: 2 # Very powerful multitool to balance out the desire to sell or scrap for points
|
||||||
useSound: /Audio/Items/drill_use.ogg
|
useSound: /Audio/Items/drill_use.ogg
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- Multitool
|
||||||
- type: MultipleTool
|
- type: MultipleTool
|
||||||
statusShowBehavior: true
|
statusShowBehavior: true
|
||||||
entries:
|
entries:
|
||||||
|
|||||||
@@ -498,6 +498,9 @@
|
|||||||
- type: Tag
|
- type: Tag
|
||||||
id: Mop
|
id: Mop
|
||||||
|
|
||||||
|
- type: Tag
|
||||||
|
id: Multitool
|
||||||
|
|
||||||
- type: Tag
|
- type: Tag
|
||||||
id: NoSpinOnThrow
|
id: NoSpinOnThrow
|
||||||
|
|
||||||
|
|||||||
39
Resources/ServerInfo/Guidebook/Network_Configurator.xml
Normal file
39
Resources/ServerInfo/Guidebook/Network_Configurator.xml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<Document>
|
||||||
|
# Network Configurator
|
||||||
|
The network configurator allows you to manipulate device lists and link devices together.
|
||||||
|
<Box>
|
||||||
|
<GuideEntityEmbed Entity="NetworkConfigurator"/>
|
||||||
|
</Box>
|
||||||
|
The configurator has two modes: List and Link. You can press [color=gray]Alt+Z[/color] or [color=gray]Alt+Y[/color] to switch between them.
|
||||||
|
|
||||||
|
## List Mode
|
||||||
|
In list mode you can click on network devices to save them on the configurator and then on a network device that has a device list like the [color=#a4885c]Air Alarm[/color].
|
||||||
|
|
||||||
|
When clicking on a device like the Air Alarm, a UI will open displaying the list currently saved on the device and buttons to manipulate that list.
|
||||||
|
|
||||||
|
You can:
|
||||||
|
- Replace the current list with the one saved on the configurator
|
||||||
|
- Add the list on the configurator to the current one
|
||||||
|
- Clear the current list
|
||||||
|
- Copy the current list to the configurator
|
||||||
|
- Visualize the connections to the devices on the current list
|
||||||
|
|
||||||
|
Pressing [color=gray]z[/color] or [color=gray]y[/color] opens the list saved on the configurator where you can remove saved devices.
|
||||||
|
|
||||||
|
## Link Mode
|
||||||
|
With link mode you can click on a device that is capable of device linking and click on any other device that is either
|
||||||
|
a sink or source.
|
||||||
|
|
||||||
|
For example, first clicking on a source like a [color=#a4885c]signal button[/color] and then on sink like a
|
||||||
|
[color=#a4885c]small light[/color] opens a UI that displays the source ports on the left side and the sink ports on the right.
|
||||||
|
|
||||||
|
Now you can eiter click [color=gray]link defaults[/color] to link the default ports for a source + sink combination or press on a source and then a sink port to connect them.
|
||||||
|
|
||||||
|
An example of a default link for the aformentioned combinaton of devices would be:
|
||||||
|
<Box>
|
||||||
|
[color=cyan]Pressed 🠒 Toggle[/color]
|
||||||
|
</Box>
|
||||||
|
When you're done connecting the ports you want you can click on [color=gray]ok[/color] to close the UI.
|
||||||
|
|
||||||
|
You can quickly link multiple devices to their default port by first clicking on a device that can be linked and then using [color=gray]alt+left mouse button[/color] on the devices you want to link together.
|
||||||
|
</Document>
|
||||||
25
Resources/ServerInfo/Guidebook/Networking.xml
Normal file
25
Resources/ServerInfo/Guidebook/Networking.xml
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<Document>
|
||||||
|
# Networking
|
||||||
|
Some devices on the station need to communicate with each other, and they do this by utilizing device networking.
|
||||||
|
With networking machines and devices can send arbitrary data between each other.
|
||||||
|
There are multiple networks that get used, such as the wireless and wired network.
|
||||||
|
Each network device has a frequency it receives on. PDAs for example, use the frequency: [color=green]220.2[/color]
|
||||||
|
|
||||||
|
## Device Lists
|
||||||
|
Some devices need to know what other devices to communicate with specifically.
|
||||||
|
<Box>
|
||||||
|
<GuideEntityEmbed Entity="AirAlarm"/>
|
||||||
|
</Box>
|
||||||
|
Air alarms for example require you to tell it which vents, scrubbers, sensors, and firelocks to interact with.
|
||||||
|
You do that by using the Network Configurator.
|
||||||
|
|
||||||
|
## Linking
|
||||||
|
If devices basic or still more advanced but need finer control of how and what connects to each other they will generally use device linking.
|
||||||
|
<Box>
|
||||||
|
<GuideEntityEmbed Entity="SignalSwitch"/>
|
||||||
|
<GuideEntityEmbed Entity="Airlock"/>
|
||||||
|
</Box>
|
||||||
|
With linking you can connect the outputs of a device like [color=gray]On[/color] or [color=gray]Off[/color] with the inputs of a device like the airlocks
|
||||||
|
[color=gray]Open[/color] or [color=gray]Close[/color] inputs.
|
||||||
|
The Network Configurator is also used for linking devices together.
|
||||||
|
</Document>
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 145 B |
Binary file not shown.
|
After Width: | Height: | Size: 332 B |
Binary file not shown.
|
After Width: | Height: | Size: 312 B |
Binary file not shown.
|
After Width: | Height: | Size: 320 B |
@@ -0,0 +1,32 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC-BY-SA-3.0",
|
||||||
|
"copyright": "Made by Julian Giebel <juliangiebel@live.de> for ss14",
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "icon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mode-list"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "mode-link"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "inhand-left",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "inhand-right",
|
||||||
|
"directions": 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "equipped-BELT",
|
||||||
|
"directions": 4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 109 B |
Binary file not shown.
|
After Width: | Height: | Size: 104 B |
Reference in New Issue
Block a user