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 JetBrains.Annotations;
|
||||
using Content.Client.NetworkConfigurator.Systems;
|
||||
using Content.Shared.DeviceNetwork;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
||||
@@ -8,17 +8,18 @@ namespace Content.Client.NetworkConfigurator;
|
||||
public sealed class NetworkConfiguratorBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
|
||||
private NetworkConfiguratorListMenu? _listMenu;
|
||||
private NetworkConfiguratorConfigurationMenu? _configurationMenu;
|
||||
private NetworkConfiguratorLinkMenu? _linkMenu;
|
||||
|
||||
private NetworkConfiguratorSystem _netConfig;
|
||||
private DeviceListSystem _deviceList;
|
||||
|
||||
public NetworkConfiguratorBoundUserInterface(ClientUserInterfaceComponent owner, Enum uiKey) : base(owner, uiKey)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_netConfig = _entityManager.System<NetworkConfiguratorSystem>();
|
||||
_deviceList = _entityManager.System<DeviceListSystem>();
|
||||
}
|
||||
|
||||
public void OnRemoveButtonPressed(string address)
|
||||
@@ -36,7 +37,7 @@ public sealed class NetworkConfiguratorBoundUserInterface : BoundUserInterface
|
||||
_listMenu = new NetworkConfiguratorListMenu(this);
|
||||
_listMenu.OnClose += Close;
|
||||
_listMenu.ClearButton.OnPressed += _ => OnClearButtonPressed();
|
||||
_listMenu.OpenCentered();
|
||||
_listMenu.OpenCenteredRight();
|
||||
break;
|
||||
case NetworkConfiguratorUiKey.Configure:
|
||||
_configurationMenu = new NetworkConfiguratorConfigurationMenu();
|
||||
@@ -50,6 +51,11 @@ public sealed class NetworkConfiguratorBoundUserInterface : BoundUserInterface
|
||||
_configurationMenu.Show.Pressed = _netConfig.ConfiguredListIsTracked(Owner.Owner);
|
||||
_configurationMenu.OpenCentered();
|
||||
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:
|
||||
_configurationMenu?.UpdateState(listState);
|
||||
break;
|
||||
case DeviceLinkUserInterfaceState linkState:
|
||||
_linkMenu?.UpdateState(linkState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<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="350 100">
|
||||
Title="{Loc 'network-configurator-title-device-configuration'}" MinSize="350 100">
|
||||
<BoxContainer Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True">
|
||||
<networkConfigurator:NetworkConfiguratorDeviceList Name="DeviceList" MinHeight="500" />
|
||||
<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="Show" Text="Show" Access="Public" ToggleMode="True" ToolTip="{Loc 'network-configurator-tooltip-show'}" HorizontalExpand="True" StyleClasses="ButtonSquare"/>
|
||||
</BoxContainer>
|
||||
<Label Name="Count" HorizontalAlignment="Right" />
|
||||
<Label Name="Count" StyleClasses="LabelSubText" HorizontalAlignment="Right" Margin="0 0 12 8"/>
|
||||
</BoxContainer>
|
||||
</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.Components;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<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="220 400">
|
||||
Title="{Loc 'network-configurator-title-saved-devices'}" MinSize="220 400">
|
||||
<BoxContainer Orientation="Vertical" VerticalExpand="True">
|
||||
<networkConfigurator:NetworkConfiguratorDeviceList Name="DeviceList" />
|
||||
<BoxContainer Orientation="Horizontal" Margin="8 8 8 8">
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.DeviceNetwork;
|
||||
using Robust.Client.Graphics;
|
||||
|
||||
namespace Content.Client.NetworkConfigurator;
|
||||
namespace Content.Client.NetworkConfigurator.Systems;
|
||||
|
||||
public sealed class DeviceListSystem : SharedDeviceListSystem
|
||||
{
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
using System.Linq;
|
||||
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.DeviceNetwork;
|
||||
using Content.Shared.DeviceNetwork.Components;
|
||||
using Content.Shared.DeviceNetwork.Systems;
|
||||
using Content.Shared.Input;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Input;
|
||||
using Robust.Client.Player;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Console;
|
||||
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
|
||||
{
|
||||
@@ -17,6 +24,7 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||
[Dependency] private readonly IOverlayManager _overlay = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly ActionsSystem _actions = default!;
|
||||
[Dependency] private readonly IInputManager _inputManager = default!;
|
||||
|
||||
private const string Action = "ClearNetworkLinkOverlays";
|
||||
|
||||
@@ -25,6 +33,13 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||
base.Initialize();
|
||||
|
||||
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)
|
||||
@@ -102,6 +117,41 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||
|
||||
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
|
||||
|
||||
@@ -82,7 +82,6 @@ namespace Content.IntegrationTests.Tests
|
||||
await server.WaitPost(() =>
|
||||
{
|
||||
entityMan = IoCManager.Resolve<IEntityManager>();
|
||||
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||
|
||||
var prototypeMan = IoCManager.Resolve<IPrototypeManager>();
|
||||
var protoIds = prototypeMan
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
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;
|
||||
|
||||
namespace Content.Server.Atmos.Piping.Binary.EntitySystems;
|
||||
|
||||
public sealed class SignalControlledValveSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SignalLinkerSystem _signal = default!;
|
||||
[Dependency] private readonly DeviceLinkSystem _signal = default!;
|
||||
[Dependency] private readonly GasValveSystem _valve = default!;
|
||||
|
||||
public override void Initialize()
|
||||
@@ -19,10 +20,10 @@ public sealed class SignalControlledValveSystem : EntitySystem
|
||||
|
||||
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))
|
||||
return;
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Atmos.Monitor.Components;
|
||||
using Content.Server.Atmos.Monitor.Systems;
|
||||
using Content.Server.Atmos.Piping.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.Components;
|
||||
using Content.Server.DeviceNetwork.Systems;
|
||||
using Content.Server.MachineLinking.Events;
|
||||
using Content.Server.MachineLinking.System;
|
||||
using Content.Server.NodeContainer;
|
||||
using Content.Server.NodeContainer.Nodes;
|
||||
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 DeviceNetworkSystem _deviceNetSystem = default!;
|
||||
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
|
||||
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly SharedAmbientSoundSystem _ambientSoundSystem = 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)
|
||||
{
|
||||
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)
|
||||
return;
|
||||
|
||||
@@ -2,7 +2,7 @@ using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Server.Access.Systems;
|
||||
using Content.Server.Cargo.Components;
|
||||
using Content.Server.Labels.Components;
|
||||
using Content.Server.MachineLinking.System;
|
||||
using Content.Server.DeviceLinking.Systems;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Station.Systems;
|
||||
using Content.Shared.Access.Systems;
|
||||
@@ -34,7 +34,7 @@ namespace Content.Server.Cargo.Systems
|
||||
|
||||
[Dependency] private readonly IdCardSystem _idCardSystem = 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 StationSystem _station = 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)
|
||||
{
|
||||
_linker.EnsureReceiverPorts(uid, telepad.ReceiverPort);
|
||||
_linker.EnsureSinkPorts(uid, telepad.ReceiverPort);
|
||||
}
|
||||
|
||||
private void SetEnabled(CargoTelepadComponent component, ApcPowerReceiverComponent? receiver = null,
|
||||
|
||||
@@ -4,11 +4,10 @@ using Robust.Shared.Timing;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Medical.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.Mind.Components;
|
||||
using Content.Server.MachineLinking.System;
|
||||
using Content.Server.MachineLinking.Events;
|
||||
using Content.Server.UserInterface;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Robust.Server.GameObjects;
|
||||
@@ -16,7 +15,8 @@ using Robust.Server.Player;
|
||||
using Content.Shared.Cloning.CloningConsole;
|
||||
using Content.Shared.Cloning;
|
||||
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.Mobs.Components;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
@@ -26,7 +26,7 @@ namespace Content.Server.Cloning
|
||||
[UsedImplicitly]
|
||||
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 IPlayerManager _playerManager = default!;
|
||||
[Dependency] private readonly CloningSystem _cloningSystem = default!;
|
||||
@@ -48,7 +48,7 @@ namespace Content.Server.Cloning
|
||||
|
||||
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)
|
||||
{
|
||||
@@ -72,20 +72,20 @@ namespace Content.Server.Cloning
|
||||
|
||||
private void OnMapInit(EntityUid uid, CloningConsoleComponent component, MapInitEvent args)
|
||||
{
|
||||
if (!TryComp<SignalTransmitterComponent>(uid, out var receiver))
|
||||
if (!TryComp<DeviceLinkSourceComponent>(uid, out var receiver))
|
||||
return;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -93,15 +93,15 @@ namespace Content.Server.Cloning
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
RecheckConnections(uid, component.CloningPod, component.GeneticScanner, component);
|
||||
|
||||
@@ -10,15 +10,15 @@ using Content.Server.Power.EntitySystems;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.EUI;
|
||||
using Content.Server.Humanoid;
|
||||
using Content.Server.MachineLinking.System;
|
||||
using Content.Server.MachineLinking.Events;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Server.Fluids.EntitySystems;
|
||||
using Content.Server.Chat.Systems;
|
||||
using Content.Server.Construction;
|
||||
using Content.Server.DeviceLinking.Events;
|
||||
using Content.Server.DeviceLinking.Systems;
|
||||
using Content.Server.Materials;
|
||||
using Content.Server.Stack;
|
||||
using Content.Server.Jobs;
|
||||
using Content.Shared.DeviceLinking.Events;
|
||||
using Content.Shared.Emag.Components;
|
||||
using Content.Shared.Humanoid;
|
||||
using Content.Shared.Humanoid.Prototypes;
|
||||
@@ -43,7 +43,7 @@ namespace Content.Server.Cloning
|
||||
{
|
||||
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 IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly EuiManager _euiManager = null!;
|
||||
@@ -84,7 +84,7 @@ namespace Content.Server.Cloning
|
||||
private void OnComponentInit(EntityUid uid, CloningPodComponent clonePod, ComponentInit args)
|
||||
{
|
||||
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)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
namespace Content.Server.MachineLinking.Components;
|
||||
namespace Content.Server.DeviceLinking.Components;
|
||||
|
||||
/// <summary>
|
||||
/// 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>
|
||||
/// This is used for automatic linkage with various receivers, like shutters.
|
||||
@@ -1,7 +1,7 @@
|
||||
using Content.Shared.MachineLinking;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.MachineLinking.Components
|
||||
namespace Content.Server.DeviceLinking.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed class DoorSignalControlComponent : Component
|
||||
@@ -2,7 +2,7 @@ using Content.Shared.MachineLinking;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.MachineLinking.Components
|
||||
namespace Content.Server.DeviceLinking.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// 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 Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.MachineLinking.Components
|
||||
namespace Content.Server.DeviceLinking.Components
|
||||
{
|
||||
/// <summary>
|
||||
/// Sends out a signal to machine linked objects.
|
||||
@@ -1,7 +1,8 @@
|
||||
using Content.Shared.DeviceLinking;
|
||||
using Content.Shared.MachineLinking;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.MachineLinking.Components
|
||||
namespace Content.Server.DeviceLinking.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
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>
|
||||
/// This handles automatically linking autolinked entities at round-start.
|
||||
/// </summary>
|
||||
public sealed class AutoLinkSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SignalLinkerSystem _signalLinkerSystem = default!;
|
||||
[Dependency] private readonly DeviceLinkSystem _deviceLinkSystem = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
@@ -29,7 +30,7 @@ public sealed class AutoLinkSystem : EntitySystem
|
||||
if (rxXform.GridUid != xform.GridUid)
|
||||
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.MachineLinking.Events;
|
||||
using Content.Server.DeviceLinking.Components;
|
||||
using Content.Server.DeviceLinking.Events;
|
||||
using Content.Server.Doors.Systems;
|
||||
using Content.Server.MachineLinking.System;
|
||||
using Content.Shared.Doors.Components;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace Content.Server.MachineLinking.System
|
||||
namespace Content.Server.DeviceLinking.Systems
|
||||
{
|
||||
[UsedImplicitly]
|
||||
public sealed class DoorSignalControlSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly DoorSystem _doorSystem = default!;
|
||||
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
|
||||
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -21,10 +22,10 @@ namespace Content.Server.MachineLinking.System
|
||||
|
||||
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))
|
||||
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.Interaction;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server.MachineLinking.System
|
||||
namespace Content.Server.DeviceLinking.Systems
|
||||
{
|
||||
public sealed class SignalSwitchSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
|
||||
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -20,7 +21,7 @@ namespace Content.Server.MachineLinking.System
|
||||
|
||||
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)
|
||||
@@ -1,13 +1,13 @@
|
||||
using Content.Server.DeviceLinking.Components;
|
||||
using Content.Server.Explosion.EntitySystems;
|
||||
using Content.Server.MachineLinking.Components;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Timing;
|
||||
|
||||
namespace Content.Server.MachineLinking.System;
|
||||
namespace Content.Server.DeviceLinking.Systems;
|
||||
|
||||
public sealed class SignallerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SignalLinkerSystem _signal = default!;
|
||||
[Dependency] private readonly DeviceLinkSystem _link = default!;
|
||||
[Dependency] private readonly UseDelaySystem _useDelay = default!;
|
||||
|
||||
public override void Initialize()
|
||||
@@ -21,14 +21,14 @@ public sealed class SignallerSystem : EntitySystem
|
||||
|
||||
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)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
_signal.InvokePort(uid, component.Port);
|
||||
_link.InvokePort(uid, component.Port);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public sealed class SignallerSystem : EntitySystem
|
||||
if (hasUseDelay)
|
||||
_useDelay.BeginDelay(uid, useDelay);
|
||||
|
||||
_signal.InvokePort(uid, component.Port);
|
||||
_link.InvokePort(uid, component.Port);
|
||||
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.MachineLinking;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.MachineLinking.System
|
||||
namespace Content.Server.DeviceLinking.Systems
|
||||
{
|
||||
public sealed class TwoWayLeverSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
|
||||
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
|
||||
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)
|
||||
{
|
||||
_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)
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Linq;
|
||||
using Content.Server.DeviceNetwork.Components;
|
||||
using Content.Shared.DeviceNetwork;
|
||||
using Content.Shared.DeviceNetwork.Components;
|
||||
using Content.Shared.Interaction;
|
||||
using JetBrains.Annotations;
|
||||
|
||||
|
||||
@@ -1,16 +1,22 @@
|
||||
using System.Linq;
|
||||
using Content.Server.DeviceLinking.Systems;
|
||||
using Content.Server.DeviceNetwork.Components;
|
||||
using Content.Server.UserInterface;
|
||||
using Content.Shared.Access.Components;
|
||||
using Content.Shared.Access.Systems;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.DeviceLinking;
|
||||
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.Popups;
|
||||
using Content.Shared.Verbs;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.DeviceNetwork.Systems;
|
||||
@@ -19,11 +25,14 @@ namespace Content.Server.DeviceNetwork.Systems;
|
||||
public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||
{
|
||||
[Dependency] private readonly DeviceListSystem _deviceListSystem = default!;
|
||||
[Dependency] private readonly DeviceLinkSystem _deviceLinkSystem = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _uiSystem = default!;
|
||||
[Dependency] private readonly AccessReaderSystem _accessSystem = 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()
|
||||
{
|
||||
@@ -32,17 +41,23 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||
SubscribeLocalEvent<NetworkConfiguratorComponent, MapInitEvent>(OnMapInit);
|
||||
|
||||
//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
|
||||
SubscribeLocalEvent<NetworkConfiguratorComponent, GetVerbsEvent<UtilityVerb>>(OnAddInteractVerb);
|
||||
SubscribeLocalEvent<DeviceNetworkComponent, GetVerbsEvent<AlternativeVerb>>(OnAddAlternativeSaveDeviceVerb);
|
||||
SubscribeLocalEvent<NetworkConfiguratorComponent, GetVerbsEvent<AlternativeVerb>>(OnAddSwitchModeVerb);
|
||||
|
||||
//UI
|
||||
SubscribeLocalEvent<NetworkConfiguratorComponent, BoundUIClosedEvent>(OnUiClosed);
|
||||
SubscribeLocalEvent<NetworkConfiguratorComponent, NetworkConfiguratorRemoveDeviceMessage>(OnRemoveDevice);
|
||||
SubscribeLocalEvent<NetworkConfiguratorComponent, NetworkConfiguratorClearDevicesMessage>(OnClearDevice);
|
||||
SubscribeLocalEvent<NetworkConfiguratorComponent, NetworkConfiguratorLinksSaveMessage>(OnSaveLinks);
|
||||
SubscribeLocalEvent<NetworkConfiguratorComponent, NetworkConfiguratorClearLinksMessage>(OnClearLinks);
|
||||
SubscribeLocalEvent<NetworkConfiguratorComponent, NetworkConfiguratorToggleLinkMessage>(OnToggleLinks);
|
||||
SubscribeLocalEvent<NetworkConfiguratorComponent, NetworkConfiguratorButtonPressedMessage>(OnConfigButtonPressed);
|
||||
SubscribeLocalEvent<NetworkConfiguratorComponent, ActivatableUIOpenAttemptEvent>(OnUiOpenAttempt);
|
||||
|
||||
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.
|
||||
_uiSystem.GetUiOrNull(uid, NetworkConfiguratorUiKey.Configure)?.CloseAll();
|
||||
_uiSystem.TryCloseAll(uid, NetworkConfiguratorUiKey.Configure);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMapInit(EntityUid uid, NetworkConfiguratorComponent component, MapInitEvent args)
|
||||
{
|
||||
component.Devices.Clear();
|
||||
UpdateUiState(uid, component);
|
||||
UpdateListUiState(uid, component);
|
||||
}
|
||||
|
||||
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)),
|
||||
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)
|
||||
{
|
||||
if (!TryComp(target, out AccessReaderComponent? reader) || user == null)
|
||||
return false;
|
||||
return true;
|
||||
|
||||
if (_accessSystem.IsAllowed(user.Value, reader))
|
||||
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);
|
||||
|
||||
return false;
|
||||
@@ -137,26 +199,80 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||
|
||||
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
|
||||
|
||||
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>
|
||||
/// Either adds a device to the device list or shows the config ui if the target is ant entity with a device list
|
||||
/// </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;
|
||||
|
||||
if (!HasComp<DeviceListComponent>(target))
|
||||
if (configurator.LinkModeActive)
|
||||
{
|
||||
TryAddNetworkDevice(target, user, component);
|
||||
TryLinkDevice(uid, configurator, target, user);
|
||||
return;
|
||||
}
|
||||
|
||||
OpenDeviceListUi(target, user, component);
|
||||
if (!HasComp<DeviceListComponent>(target))
|
||||
{
|
||||
TryAddNetworkDevice(target, user, configurator);
|
||||
return;
|
||||
}
|
||||
|
||||
OpenDeviceListUi(target, user, configurator);
|
||||
}
|
||||
|
||||
#endregion
|
||||
@@ -166,22 +282,32 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||
/// <summary>
|
||||
/// Adds the interaction verb which is either configuring device lists or saving a device onto the configurator
|
||||
/// </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;
|
||||
|
||||
var isDeviceList = HasComp<DeviceListComponent>(args.Target);
|
||||
|
||||
UtilityVerb verb = new()
|
||||
var verb = new UtilityVerb
|
||||
{
|
||||
Text = Loc.GetString(isDeviceList ? "network-configurator-configure" : "network-configurator-save-device"),
|
||||
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),
|
||||
Act = () => OnUsed(uid, configurator, args.Target, args.User),
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -193,8 +319,39 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||
/// </summary>
|
||||
private void OnAddAlternativeSaveDeviceVerb(EntityUid uid, DeviceNetworkComponent component, GetVerbsEvent<AlternativeVerb> args)
|
||||
{
|
||||
if (!args.CanAccess || !args.CanInteract || !args.Using.HasValue || !HasComp<NetworkConfiguratorComponent>(args.Using.Value)
|
||||
|| !HasComp<DeviceListComponent>(args.Target))
|
||||
if (!args.CanAccess || !args.CanInteract || !args.Using.HasValue
|
||||
|| !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;
|
||||
|
||||
AlternativeVerb verb = new()
|
||||
@@ -211,11 +368,57 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||
|
||||
#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>
|
||||
/// Opens the config ui. It can be used to modify the devices in the targets device list.
|
||||
/// </summary>
|
||||
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))
|
||||
return;
|
||||
|
||||
@@ -233,7 +436,7 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||
/// <summary>
|
||||
/// Sends the list of saved devices to the ui
|
||||
/// </summary>
|
||||
private void UpdateUiState(EntityUid uid, NetworkConfiguratorComponent component)
|
||||
private void UpdateListUiState(EntityUid uid, NetworkConfiguratorComponent component)
|
||||
{
|
||||
HashSet<(string address, string name)> devices = new();
|
||||
HashSet<string> invalidDevices = new();
|
||||
@@ -264,6 +467,12 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||
private void OnUiClosed(EntityUid uid, NetworkConfiguratorComponent component, BoundUIClosedEvent args)
|
||||
{
|
||||
component.ActiveDeviceList = null;
|
||||
|
||||
if (args.UiKey is NetworkConfiguratorUiKey.Link)
|
||||
{
|
||||
component.ActiveDeviceLink = null;
|
||||
component.DeviceLinkTarget = null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -272,7 +481,7 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||
private void OnRemoveDevice(EntityUid uid, NetworkConfiguratorComponent component, NetworkConfiguratorRemoveDeviceMessage args)
|
||||
{
|
||||
component.Devices.Remove(args.Address);
|
||||
UpdateUiState(uid, component);
|
||||
UpdateListUiState(uid, component);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -281,7 +490,61 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||
private void OnClearDevice(EntityUid uid, NetworkConfiguratorComponent component, NetworkConfiguratorClearDevicesMessage _)
|
||||
{
|
||||
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>
|
||||
@@ -307,11 +570,9 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||
break;
|
||||
case NetworkConfiguratorButtonKey.Copy:
|
||||
component.Devices = _deviceListSystem.GetDeviceList(component.ActiveDeviceList.Value);
|
||||
UpdateUiState(uid, component);
|
||||
UpdateListUiState(uid, component);
|
||||
return;
|
||||
case NetworkConfiguratorButtonKey.Show:
|
||||
// This should be done client-side.
|
||||
// _deviceListSystem.ToggleVisualization(component.ActiveDeviceList.Value);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -330,5 +591,11 @@ public sealed class NetworkConfiguratorSystem : SharedNetworkConfiguratorSystem
|
||||
_deviceListSystem.GetDeviceList(component.ActiveDeviceList.Value)
|
||||
.Select(v => (v.Key, MetaData(v.Value).EntityName)).ToHashSet()));
|
||||
}
|
||||
|
||||
private void OnUiOpenAttempt(EntityUid uid, NetworkConfiguratorComponent configurator, ActivatableUIOpenAttemptEvent args)
|
||||
{
|
||||
if (configurator.LinkModeActive)
|
||||
args.Cancel();
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Server.DeviceLinking.Events;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Shared.Tools.Components;
|
||||
@@ -8,7 +9,6 @@ using Content.Shared.Doors.Systems;
|
||||
using Content.Shared.Interaction;
|
||||
using Robust.Server.GameObjects;
|
||||
using Content.Shared.Wires;
|
||||
using Content.Server.MachineLinking.Events;
|
||||
using Content.Server.MachineLinking.System;
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
@@ -1,20 +1,19 @@
|
||||
using Content.Server.DeviceLinking.Events;
|
||||
using Content.Server.DeviceLinking.Systems;
|
||||
using Content.Server.Explosion.Components;
|
||||
using Content.Server.MachineLinking.Events;
|
||||
using Content.Server.MachineLinking.System;
|
||||
|
||||
namespace Content.Server.Explosion.EntitySystems
|
||||
{
|
||||
public sealed partial class TriggerSystem
|
||||
{
|
||||
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
|
||||
|
||||
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
||||
private void InitializeSignal()
|
||||
{
|
||||
SubscribeLocalEvent<TriggerOnSignalComponent,SignalReceivedEvent>(OnSignalReceived);
|
||||
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)
|
||||
return;
|
||||
@@ -23,7 +22,7 @@ namespace Content.Server.Explosion.EntitySystems
|
||||
}
|
||||
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.Ghost;
|
||||
using Content.Server.Light.Components;
|
||||
using Content.Server.MachineLinking.Events;
|
||||
using Content.Server.MachineLinking.System;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Temperature.Components;
|
||||
using Content.Shared.Audio;
|
||||
@@ -22,6 +20,8 @@ using Robust.Shared.Player;
|
||||
using Robust.Shared.Timing;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Server.Emp;
|
||||
using Content.Server.DeviceLinking.Events;
|
||||
using Content.Server.DeviceLinking.Systems;
|
||||
|
||||
namespace Content.Server.Light.EntitySystems
|
||||
{
|
||||
@@ -37,7 +37,7 @@ namespace Content.Server.Light.EntitySystems
|
||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly IAdminLogManager _adminLogger= 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 SharedDoAfterSystem _doAfterSystem = 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)
|
||||
{
|
||||
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)
|
||||
@@ -354,7 +354,7 @@ namespace Content.Server.Light.EntitySystems
|
||||
_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)
|
||||
SetState(uid, false, component);
|
||||
|
||||
@@ -3,13 +3,13 @@ using Content.Server.MachineLinking.System;
|
||||
namespace Content.Server.MachineLinking.Components
|
||||
{
|
||||
[DataDefinition]
|
||||
public struct PortIdentifier
|
||||
public readonly struct PortIdentifier
|
||||
{
|
||||
[DataField("uid")]
|
||||
public EntityUid Uid;
|
||||
public readonly EntityUid Uid;
|
||||
|
||||
[DataField("port")]
|
||||
public string Port;
|
||||
public readonly 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.Diagnostics.CodeAnalysis;
|
||||
using Content.Server.DeviceLinking.Events;
|
||||
using Content.Server.MachineLinking.Components;
|
||||
using Content.Server.MachineLinking.Events;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Tools;
|
||||
using Content.Shared.DeviceLinking.Events;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.MachineLinking;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Player;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Content.Shared.MachineLinking.Events;
|
||||
using Content.Server.Database;
|
||||
|
||||
namespace Content.Server.MachineLinking.System
|
||||
{
|
||||
@@ -140,7 +138,10 @@ namespace Content.Server.MachineLinking.System
|
||||
return;
|
||||
|
||||
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)
|
||||
|
||||
@@ -1,30 +1,28 @@
|
||||
using Content.Server.Climbing;
|
||||
using Content.Server.Cloning;
|
||||
using Content.Server.Medical.Components;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Shared.Destructible;
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.DragDrop;
|
||||
using Content.Shared.Movement.Events;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Containers;
|
||||
using Content.Server.MachineLinking.System;
|
||||
using Content.Server.MachineLinking.Events;
|
||||
using Content.Server.Cloning.Components;
|
||||
using Content.Server.Construction;
|
||||
using Content.Server.DeviceLinking.Systems;
|
||||
using Content.Shared.DeviceLinking.Events;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Robust.Server.Containers;
|
||||
using Robust.Server.GameObjects;
|
||||
using static Content.Shared.MedicalScanner.SharedMedicalScannerComponent; // Hmm...
|
||||
|
||||
namespace Content.Server.Medical
|
||||
{
|
||||
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 ClimbSystem _climbSystem = default!;
|
||||
[Dependency] private readonly CloningConsoleSystem _cloningConsoleSystem = default!;
|
||||
@@ -70,7 +68,7 @@ namespace Content.Server.Medical
|
||||
{
|
||||
base.Initialize();
|
||||
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)
|
||||
|
||||
@@ -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.Materials;
|
||||
using Content.Server.Power.Components;
|
||||
@@ -9,7 +11,6 @@ using Content.Shared.Physics.Controllers;
|
||||
using Robust.Shared.Physics;
|
||||
using Robust.Shared.Physics.Collision.Shapes;
|
||||
using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Physics.Dynamics;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
|
||||
namespace Content.Server.Physics.Controllers;
|
||||
@@ -17,8 +18,8 @@ namespace Content.Server.Physics.Controllers;
|
||||
public sealed class ConveyorController : SharedConveyorController
|
||||
{
|
||||
[Dependency] private readonly FixtureSystem _fixtures = default!;
|
||||
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
||||
[Dependency] private readonly MaterialReclaimerSystem _materialReclaimer = default!;
|
||||
[Dependency] private readonly SignalLinkerSystem _signalSystem = default!;
|
||||
[Dependency] private readonly SharedBroadphaseSystem _broadphase = 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)
|
||||
{
|
||||
_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))
|
||||
{
|
||||
@@ -76,7 +77,7 @@ public sealed class ConveyorController : SharedConveyorController
|
||||
_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)
|
||||
SetState(uid, ConveyorState.Off, component);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Construction;
|
||||
using Content.Server.DeviceLinking.Events;
|
||||
using Content.Server.MachineLinking.Components;
|
||||
using Content.Server.MachineLinking.Events;
|
||||
using Content.Server.Paper;
|
||||
using Content.Server.Power.Components;
|
||||
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.Events;
|
||||
using Content.Shared.Audio;
|
||||
using Content.Shared.MachineLinking.Events;
|
||||
using Content.Shared.DeviceLinking.Events;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Research.Components;
|
||||
using Content.Shared.Xenoarchaeology.Equipment;
|
||||
@@ -168,10 +168,10 @@ public sealed class ArtifactAnalyzerSystem : EntitySystem
|
||||
|
||||
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;
|
||||
|
||||
component.AnalyzerEntity = args.Receiver;
|
||||
component.AnalyzerEntity = args.Sink;
|
||||
analyzer.Console = uid;
|
||||
|
||||
UpdateUserInterface(uid, component);
|
||||
|
||||
@@ -5,9 +5,9 @@ using Content.Shared.Emag.Components;
|
||||
using Content.Shared.Emag.Systems;
|
||||
using Content.Shared.PDA;
|
||||
using Content.Shared.Access.Components;
|
||||
using Content.Shared.DeviceLinking.Events;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.MachineLinking.Events;
|
||||
using Content.Shared.StationRecords;
|
||||
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
|
||||
{
|
||||
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;
|
||||
|
||||
namespace Content.Shared.MachineLinking
|
||||
namespace Content.Shared.DeviceLinking
|
||||
{
|
||||
[Serializable, NetSerializable]
|
||||
public enum TwoWayLeverVisuals : byte
|
||||
@@ -1,7 +1,7 @@
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.DeviceNetwork;
|
||||
namespace Content.Shared.DeviceNetwork.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
[NetworkedComponent]
|
||||
|
||||
@@ -1,14 +1,24 @@
|
||||
using Content.Shared.DeviceLinking;
|
||||
using Content.Shared.DeviceNetwork.Systems;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
namespace Content.Shared.DeviceNetwork;
|
||||
namespace Content.Shared.DeviceNetwork.Components;
|
||||
|
||||
[RegisterComponent]
|
||||
[NetworkedComponent]
|
||||
[Access(typeof(SharedNetworkConfiguratorSystem))]
|
||||
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>
|
||||
/// The entity containing a <see cref="DeviceListComponent"/> this configurator is currently interacting with
|
||||
/// </summary>
|
||||
@@ -16,22 +26,48 @@ public sealed class NetworkConfiguratorComponent : Component
|
||||
public EntityUid? ActiveDeviceList = null;
|
||||
|
||||
/// <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>
|
||||
[DataField("devices")]
|
||||
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")]
|
||||
public SoundSpecifier SoundNoAccess = new SoundPathSpecifier("/Audio/Machines/custom_deny.ogg");
|
||||
|
||||
[DataField("soundSwitchMode")]
|
||||
public SoundSpecifier SoundSwitchMode = new SoundPathSpecifier("/Audio/Machines/beep.ogg");
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class NetworkConfiguratorComponentState : ComponentState
|
||||
{
|
||||
public readonly EntityUid? ActiveDeviceList;
|
||||
public readonly bool LinkModeActive;
|
||||
|
||||
public NetworkConfiguratorComponentState(EntityUid? activeDeviceList)
|
||||
public NetworkConfiguratorComponentState(EntityUid? activeDeviceList, bool linkModeActive)
|
||||
{
|
||||
ActiveDeviceList = activeDeviceList;
|
||||
LinkModeActive = linkModeActive;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,8 @@ namespace Content.Shared.DeviceNetwork;
|
||||
public enum NetworkConfiguratorUiKey
|
||||
{
|
||||
List,
|
||||
Configure
|
||||
Configure,
|
||||
Link
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
@@ -52,3 +53,33 @@ public sealed class NetworkConfiguratorButtonPressedMessage : BoundUserInterface
|
||||
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;
|
||||
|
||||
@@ -23,3 +24,24 @@ public sealed class DeviceListUserInterfaceState : BoundUserInterfaceState
|
||||
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 Content.Shared.DeviceNetwork.Components;
|
||||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared.DeviceNetwork;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using Content.Shared.Actions;
|
||||
using Content.Shared.DeviceNetwork.Components;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.DeviceNetwork;
|
||||
namespace Content.Shared.DeviceNetwork.Systems;
|
||||
|
||||
public abstract class SharedNetworkConfiguratorSystem : EntitySystem
|
||||
{
|
||||
@@ -17,7 +18,7 @@ public abstract class SharedNetworkConfiguratorSystem : EntitySystem
|
||||
private void GetNetworkConfiguratorState(EntityUid uid, NetworkConfiguratorComponent comp,
|
||||
ref ComponentGetState args)
|
||||
{
|
||||
args.State = new NetworkConfiguratorComponentState(comp.ActiveDeviceList);
|
||||
args.State = new NetworkConfiguratorComponentState(comp.ActiveDeviceList, comp.LinkModeActive);
|
||||
}
|
||||
|
||||
private void HandleNetworkConfiguratorState(EntityUid uid, NetworkConfiguratorComponent comp,
|
||||
@@ -29,9 +30,22 @@ public abstract class SharedNetworkConfiguratorSystem : EntitySystem
|
||||
}
|
||||
|
||||
comp.ActiveDeviceList = state.ActiveDeviceList;
|
||||
comp.LinkModeActive = state.LinkModeActive;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@ device-frequency-prototype-name-lights = Smart Lights
|
||||
device-frequency-prototype-name-mailing-units = Mailing Units
|
||||
device-frequency-prototype-name-pdas = PDAs
|
||||
device-frequency-prototype-name-fax = Fax
|
||||
device-frequency-prototype-name-basic-device = Basic Devices
|
||||
|
||||
## camera frequencies
|
||||
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-device-already-saved = network device: {$device} is already saved.
|
||||
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
|
||||
network-configurator-save-device = Save device
|
||||
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
|
||||
network-configurator-title-saved-devices = Saved Devices
|
||||
network-configurator-title-device-configuration = Device Configuration
|
||||
network-configurator-ui-clear-button = Clear
|
||||
network-configurator-ui-count-label = {$count} Devices
|
||||
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-copy = Copy targets device list to multitool
|
||||
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-fires = Fires & Space
|
||||
guide-entry-shuttle-craft = Shuttle-craft
|
||||
guide-entry-networking = Networking
|
||||
guide-entry-network-configurator = Network Configurator
|
||||
guide-entry-power = Power
|
||||
guide-entry-ame = Antimatter Engine (AME)
|
||||
guide-entry-singularity = Singularity
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
signal-port-selector-menu-title = Port Selector
|
||||
signal-port-selector-menu-clear = Clear
|
||||
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-description-toggle = Toggles the state of a device.
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
- id: Wirecutter
|
||||
- id: Welder
|
||||
- id: Multitool
|
||||
- id: NetworkConfigurator
|
||||
|
||||
- type: entity
|
||||
id: ClothingBeltChiefEngineerFilled
|
||||
@@ -24,6 +25,7 @@
|
||||
- id: WelderExperimental
|
||||
- id: Multitool
|
||||
- id: CableApcStack
|
||||
- id: NetworkConfigurator
|
||||
|
||||
- type: entity
|
||||
id: ClothingBeltSecurityFilled
|
||||
|
||||
@@ -86,3 +86,8 @@
|
||||
id: Fax
|
||||
name: device-frequency-prototype-name-fax
|
||||
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
|
||||
sprite: Clothing/Belt/utility.rsi
|
||||
- type: Storage
|
||||
capacity: 45
|
||||
# TODO: Fill this out more.
|
||||
whitelist:
|
||||
tags:
|
||||
@@ -26,10 +27,11 @@
|
||||
- CigPack
|
||||
- Radio
|
||||
- HolofanProjector
|
||||
- Multitool
|
||||
- AppraisalTool
|
||||
components:
|
||||
- AirlockPainter
|
||||
- SignalLinker
|
||||
- NetworkConfigurator
|
||||
- RCD
|
||||
- RCDAmmo
|
||||
- Welder
|
||||
@@ -63,8 +65,8 @@
|
||||
- Wrench
|
||||
multitool:
|
||||
whitelist:
|
||||
components:
|
||||
- SignalLinker
|
||||
tags:
|
||||
- Multitool
|
||||
sprite: Clothing/Belt/belt_overlay.rsi
|
||||
- type: Appearance
|
||||
|
||||
@@ -79,7 +81,7 @@
|
||||
- type: Clothing
|
||||
sprite: Clothing/Belt/ce.rsi
|
||||
- type: Storage
|
||||
capacity: 100
|
||||
capacity: 105
|
||||
# TODO: Fill this out more.
|
||||
whitelist:
|
||||
tags:
|
||||
@@ -96,10 +98,11 @@
|
||||
- CigPack
|
||||
- Radio
|
||||
- HolofanProjector
|
||||
- Multitool
|
||||
- AppraisalTool
|
||||
components:
|
||||
- AirlockPainter
|
||||
- SignalLinker
|
||||
- NetworkConfigurator
|
||||
- RCD
|
||||
- RCDAmmo
|
||||
- Welder
|
||||
@@ -135,8 +138,8 @@
|
||||
- Screwdriver
|
||||
multitool:
|
||||
whitelist:
|
||||
components:
|
||||
- SignalLinker
|
||||
tags:
|
||||
- Multitool
|
||||
wrench:
|
||||
whitelist:
|
||||
tags:
|
||||
|
||||
@@ -13,9 +13,9 @@
|
||||
- type: UseDelay
|
||||
- type: StaticPrice
|
||||
price: 40
|
||||
- type: SignalTransmitter
|
||||
outputs:
|
||||
Pressed: []
|
||||
- type: DeviceLinkSource
|
||||
ports:
|
||||
- Pressed
|
||||
- type: Tag
|
||||
tags:
|
||||
- Payload
|
||||
|
||||
@@ -42,7 +42,12 @@
|
||||
- type: PayloadTrigger
|
||||
components:
|
||||
- type: TriggerOnSignal
|
||||
- type: SignalReceiver
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wireless
|
||||
receiveFrequencyId: BasicDevice
|
||||
- type: WirelessNetworkConnection
|
||||
range: 200
|
||||
- type: DeviceLinkSink
|
||||
- type: StaticPrice
|
||||
price: 40
|
||||
|
||||
|
||||
@@ -108,7 +108,9 @@
|
||||
- type: Tool
|
||||
qualities:
|
||||
- Pulsing
|
||||
- type: SignalLinker
|
||||
- type: Tag
|
||||
tags:
|
||||
- Multitool
|
||||
|
||||
- type: entity
|
||||
name: cowelding tool
|
||||
|
||||
@@ -196,26 +196,62 @@
|
||||
- type: Tool
|
||||
qualities:
|
||||
- Pulsing
|
||||
- type: SignalLinker
|
||||
- type: Tag
|
||||
tags:
|
||||
- Multitool
|
||||
- DroneUsable
|
||||
- type: PhysicalComposition
|
||||
materialComposition:
|
||||
Steel: 100
|
||||
Plastic: 100
|
||||
- type: StaticPrice
|
||||
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.SignalLinkerUiKey.Key
|
||||
type: SignalPortSelectorBoundUserInterface
|
||||
- key: enum.NetworkConfiguratorUiKey.List
|
||||
type: NetworkConfiguratorBoundUserInterface
|
||||
- key: enum.NetworkConfiguratorUiKey.Configure
|
||||
type: NetworkConfiguratorBoundUserInterface
|
||||
- key: enum.NetworkConfiguratorUiKey.Link
|
||||
type: NetworkConfiguratorBoundUserInterface
|
||||
- type: Tag
|
||||
tags:
|
||||
- DroneUsable
|
||||
- type: PhysicalComposition
|
||||
materialComposition:
|
||||
Steel: 100
|
||||
Plastic: 100
|
||||
- type: StaticPrice
|
||||
price: 60
|
||||
|
||||
@@ -371,13 +407,10 @@
|
||||
- type: Item
|
||||
sprite: Objects/Tools/omnitool.rsi
|
||||
size: 20
|
||||
- type: Tag
|
||||
tags:
|
||||
- Multitool
|
||||
- type: TilePrying
|
||||
- type: SignalLinker
|
||||
requiredQuality: Pulsing
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.SignalLinkerUiKey.Key
|
||||
type: SignalPortSelectorBoundUserInterface
|
||||
- type: Tool
|
||||
qualities:
|
||||
- Screwing
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
startOnStick: true
|
||||
canToggleStartOnStick: true
|
||||
- type: TriggerOnSignal
|
||||
- type: SignalReceiver
|
||||
inputs:
|
||||
Trigger: []
|
||||
- type: DeviceLinkSink
|
||||
ports:
|
||||
- Trigger
|
||||
- type: Sticky
|
||||
stickDelay: 5
|
||||
unstickDelay: 5
|
||||
|
||||
@@ -78,12 +78,17 @@
|
||||
BoardName: "Airlock Control"
|
||||
LayoutId: Airlock
|
||||
- type: DoorSignalControl
|
||||
- type: SignalReceiver
|
||||
inputs:
|
||||
Open: []
|
||||
Close: []
|
||||
Toggle: []
|
||||
AutoClose: []
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wireless
|
||||
receiveFrequencyId: BasicDevice
|
||||
- type: WirelessNetworkConnection
|
||||
range: 200
|
||||
- type: DeviceLinkSink
|
||||
ports:
|
||||
- Open
|
||||
- Close
|
||||
- Toggle
|
||||
- AutoClose
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.WiresUiKey.Key
|
||||
|
||||
@@ -76,11 +76,16 @@
|
||||
key: walls
|
||||
mode: NoSprite
|
||||
- type: DoorSignalControl
|
||||
- type: SignalReceiver
|
||||
inputs:
|
||||
Open: []
|
||||
Close: []
|
||||
Toggle: []
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wireless
|
||||
receiveFrequencyId: BasicDevice
|
||||
- type: WirelessNetworkConnection
|
||||
range: 200
|
||||
- type: DeviceLinkSink
|
||||
ports:
|
||||
- Open
|
||||
- Close
|
||||
- Toggle
|
||||
- type: InteractionPopup
|
||||
interactSuccessString: comp-window-knock
|
||||
messagePerceivedByOthers: comp-window-knock
|
||||
|
||||
@@ -46,12 +46,17 @@
|
||||
- type: ApcPowerReceiver
|
||||
- type: ExtensionCableReceiver
|
||||
- type: DoorSignalControl
|
||||
- type: SignalReceiver
|
||||
inputs:
|
||||
Open: []
|
||||
Close: []
|
||||
Toggle: []
|
||||
AutoClose: []
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wireless
|
||||
receiveFrequencyId: BasicDevice
|
||||
- type: WirelessNetworkConnection
|
||||
range: 200
|
||||
- type: DeviceLinkSink
|
||||
ports:
|
||||
- Open
|
||||
- Close
|
||||
- Toggle
|
||||
- AutoClose
|
||||
- type: Damageable
|
||||
damageContainer: Inorganic
|
||||
damageModifierSet: Glass
|
||||
|
||||
@@ -86,18 +86,19 @@
|
||||
- type: ApcPowerReceiver
|
||||
- type: ExtensionCableReceiver
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Apc
|
||||
deviceNetId: Wireless
|
||||
receiveFrequencyId: SmartLight
|
||||
- type: ApcNetworkConnection
|
||||
- type: WirelessNetworkConnection
|
||||
range: 200
|
||||
- type: DeviceLinkSink
|
||||
ports:
|
||||
- On
|
||||
- Off
|
||||
- Toggle
|
||||
- type: Appearance
|
||||
- type: PoweredLightVisuals
|
||||
blinkingSound:
|
||||
path: "/Audio/Machines/light_tube_on.ogg"
|
||||
- type: SignalReceiver
|
||||
inputs:
|
||||
On: []
|
||||
Off: []
|
||||
Toggle: []
|
||||
|
||||
- type: entity
|
||||
id: Poweredlight
|
||||
@@ -266,16 +267,17 @@
|
||||
- type: ApcPowerReceiver
|
||||
- type: ExtensionCableReceiver
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Apc
|
||||
deviceNetId: Wireless
|
||||
receiveFrequencyId: SmartLight
|
||||
- type: ApcNetworkConnection
|
||||
- type: WirelessNetworkConnection
|
||||
range: 200
|
||||
- type: Appearance
|
||||
- type: PoweredLightVisuals
|
||||
- type: SignalReceiver
|
||||
inputs:
|
||||
On: []
|
||||
Off: []
|
||||
Toggle: []
|
||||
- type: DeviceLinkSink
|
||||
ports:
|
||||
- On
|
||||
- Off
|
||||
- Toggle
|
||||
|
||||
- type: entity
|
||||
id: PoweredSmallLight
|
||||
|
||||
@@ -91,9 +91,15 @@
|
||||
- type: ApcPowerReceiver
|
||||
- type: ExtensionCableReceiver
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Apc
|
||||
deviceNetId: Wireless
|
||||
receiveFrequencyId: SmartLight
|
||||
- type: ApcNetworkConnection
|
||||
- type: WirelessNetworkConnection
|
||||
range: 200
|
||||
- type: DeviceLinkSink
|
||||
ports:
|
||||
- On
|
||||
- Off
|
||||
- Toggle
|
||||
- type: Construction
|
||||
graph: LightFixture
|
||||
node: groundLight
|
||||
@@ -101,11 +107,6 @@
|
||||
- type: PoweredLightVisuals
|
||||
blinkingSound:
|
||||
path: "/Audio/Machines/light_tube_on.ogg"
|
||||
- type: SignalReceiver
|
||||
inputs:
|
||||
On: []
|
||||
Off: []
|
||||
Toggle: []
|
||||
|
||||
- type: entity
|
||||
id: PoweredLightPostSmall
|
||||
|
||||
@@ -378,10 +378,10 @@
|
||||
- type: DeviceList
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wired
|
||||
- type: SignalTransmitter
|
||||
transmissionRange: 5
|
||||
outputs:
|
||||
ArtifactAnalyzerSender: []
|
||||
- type: DeviceLinkSource
|
||||
range: 5
|
||||
ports:
|
||||
- ArtifactAnalyzerSender
|
||||
- type: ActivatableUI
|
||||
key: enum.ArtifactAnalzyerUiKey.Key
|
||||
- type: UserInterface
|
||||
@@ -698,11 +698,11 @@
|
||||
radius: 1.5
|
||||
energy: 1.6
|
||||
color: "#1f8c28"
|
||||
- type: SignalTransmitter
|
||||
transmissionRange: 4
|
||||
outputs:
|
||||
MedicalScannerSender: []
|
||||
CloningPodSender: []
|
||||
- type: DeviceLinkSource
|
||||
range: 4
|
||||
ports:
|
||||
- MedicalScannerSender
|
||||
- CloningPodSender
|
||||
- type: ActivatableUI
|
||||
key: enum.CloningConsoleUiKey.Key
|
||||
- type: UserInterface
|
||||
|
||||
@@ -49,10 +49,11 @@
|
||||
- type: ArtifactAnalyzer
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wired
|
||||
receiveFrequencyId: BasicDevice
|
||||
- type: DeviceList
|
||||
- type: SignalReceiver
|
||||
inputs:
|
||||
ArtifactAnalyzerReceiver: []
|
||||
- type: DeviceLinkSink
|
||||
ports:
|
||||
- ArtifactAnalyzerReceiver
|
||||
- type: Machine
|
||||
board: ArtifactAnalyzerMachineCircuitboard
|
||||
- type: PointLight
|
||||
|
||||
@@ -8,6 +8,10 @@
|
||||
- type: DeviceList
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wired
|
||||
receiveFrequencyId: BasicDevice
|
||||
- type: DeviceLinkSink
|
||||
ports:
|
||||
- CloningPodReceiver
|
||||
- type: Sprite
|
||||
netsync: false
|
||||
sprite: Structures/Machines/cloning.rsi
|
||||
@@ -34,9 +38,6 @@
|
||||
- machine_board
|
||||
- machine_parts
|
||||
- clonepod-bodyContainer
|
||||
- type: SignalReceiver
|
||||
inputs:
|
||||
CloningPodReceiver: []
|
||||
- type: EmptyOnMachineDeconstruct
|
||||
containers:
|
||||
- clonepod-bodyContainer
|
||||
|
||||
@@ -74,6 +74,7 @@
|
||||
- Wrench
|
||||
- Crowbar
|
||||
- Multitool
|
||||
- NetworkConfigurator
|
||||
- AirlockPainter
|
||||
- CableStack
|
||||
- HandheldGPSBasic
|
||||
|
||||
@@ -7,7 +7,11 @@
|
||||
- type: MedicalScanner
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wired
|
||||
receiveFrequencyId: BasicDevice
|
||||
- type: DeviceList
|
||||
- type: DeviceLinkSink
|
||||
ports:
|
||||
- MedicalScannerReceiver
|
||||
- type: Sprite
|
||||
netsync: false
|
||||
sprite: Structures/Machines/scanner.rsi
|
||||
@@ -58,9 +62,6 @@
|
||||
scanner-bodyContainer: !type:ContainerSlot
|
||||
machine_board: !type:Container
|
||||
machine_parts: !type:Container
|
||||
- type: SignalReceiver
|
||||
inputs:
|
||||
MedicalScannerReceiver: []
|
||||
- type: Damageable
|
||||
damageContainer: Inorganic
|
||||
damageModifierSet: StrongMetallic
|
||||
|
||||
@@ -42,11 +42,11 @@
|
||||
- MidImpassable
|
||||
- LowImpassable
|
||||
hard: False
|
||||
- type: SignalReceiver
|
||||
inputs:
|
||||
Reverse: []
|
||||
Forward: []
|
||||
Off: []
|
||||
- type: DeviceLinkSink
|
||||
ports:
|
||||
- Reverse
|
||||
- Forward
|
||||
- Off
|
||||
- type: Transform
|
||||
anchored: true
|
||||
noRot: false
|
||||
|
||||
@@ -208,11 +208,16 @@
|
||||
- type: PipeColorVisuals
|
||||
- type: GasValve
|
||||
- type: SignalControlledValve
|
||||
- type: SignalReceiver
|
||||
inputs:
|
||||
Open: []
|
||||
Close: []
|
||||
Toggle: []
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wireless
|
||||
receiveFrequencyId: BasicDevice
|
||||
- type: WirelessNetworkConnection
|
||||
range: 200
|
||||
- type: DeviceLinkSink
|
||||
ports:
|
||||
- Open
|
||||
- Close
|
||||
- Toggle
|
||||
- type: NodeContainer
|
||||
nodes:
|
||||
inlet:
|
||||
@@ -296,10 +301,15 @@
|
||||
inlet: inlet
|
||||
outlet: outlet
|
||||
canLink: true
|
||||
- type: SignalReceiver
|
||||
inputs:
|
||||
Pressurize: []
|
||||
Depressurize: []
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wireless
|
||||
receiveFrequencyId: BasicDevice
|
||||
- type: WirelessNetworkConnection
|
||||
range: 200
|
||||
- type: DeviceLinkSink
|
||||
ports:
|
||||
- Pressurize
|
||||
- Depressurize
|
||||
- type: Construction
|
||||
graph: GasBinary
|
||||
node: dualportventpump
|
||||
|
||||
@@ -24,10 +24,14 @@
|
||||
graph: SignalSwitchGraph
|
||||
node: SignalSwitchNode
|
||||
- type: Fixtures
|
||||
- type: SignalTransmitter
|
||||
outputs:
|
||||
On: []
|
||||
Off: []
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wireless
|
||||
- type: WirelessNetworkConnection
|
||||
range: 200
|
||||
- type: DeviceLinkSource
|
||||
ports:
|
||||
- On
|
||||
- Off
|
||||
|
||||
- type: entity
|
||||
id: SignalButton
|
||||
@@ -57,9 +61,13 @@
|
||||
graph: SignalButtonGraph
|
||||
node: SignalButtonNode
|
||||
- type: Fixtures
|
||||
- type: SignalTransmitter
|
||||
outputs:
|
||||
Pressed: []
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wireless
|
||||
- type: WirelessNetworkConnection
|
||||
range: 200
|
||||
- type: DeviceLinkSource
|
||||
ports:
|
||||
- Pressed
|
||||
- type: Damageable
|
||||
damageContainer: Inorganic
|
||||
damageModifierSet: Metallic
|
||||
@@ -153,8 +161,12 @@
|
||||
- type: Construction
|
||||
graph: LeverGraph
|
||||
node: LeverNode
|
||||
- type: SignalTransmitter
|
||||
outputs:
|
||||
Left: []
|
||||
Right: []
|
||||
Middle: []
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wireless
|
||||
- type: WirelessNetworkConnection
|
||||
range: 200
|
||||
- type: DeviceLinkSource
|
||||
ports:
|
||||
- Left
|
||||
- Right
|
||||
- Middle
|
||||
|
||||
@@ -32,9 +32,14 @@
|
||||
- type: Damageable
|
||||
damageContainer: Inorganic
|
||||
damageModifierSet: Metallic
|
||||
- type: SignalReceiver
|
||||
inputs:
|
||||
OrderReceiver: []
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wireless
|
||||
receiveFrequencyId: BasicDevice
|
||||
- type: WirelessNetworkConnection
|
||||
range: 200
|
||||
- type: DeviceLinkSink
|
||||
ports:
|
||||
- OrderReceiver
|
||||
- type: Destructible
|
||||
thresholds:
|
||||
- trigger:
|
||||
|
||||
@@ -35,11 +35,11 @@
|
||||
- LowImpassable
|
||||
hard: False
|
||||
- type: Conveyor
|
||||
- type: SignalReceiver
|
||||
inputs:
|
||||
Reverse: []
|
||||
Forward: []
|
||||
Off: []
|
||||
- type: DeviceLinkSink
|
||||
ports:
|
||||
- Reverse
|
||||
- Forward
|
||||
- Off
|
||||
- type: Appearance
|
||||
- type: GenericVisualizer
|
||||
visuals:
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
- Construction
|
||||
- Power
|
||||
- ShuttleCraft
|
||||
- Networking
|
||||
|
||||
- type: guideEntry
|
||||
id: Construction
|
||||
@@ -30,6 +31,19 @@
|
||||
name: guide-entry-shuttle-craft
|
||||
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
|
||||
id: Power
|
||||
name: guide-entry-power
|
||||
|
||||
@@ -86,6 +86,14 @@
|
||||
Steel: 200
|
||||
Plastic: 200
|
||||
|
||||
- type: latheRecipe
|
||||
id: NetworkConfigurator
|
||||
result: NetworkConfigurator
|
||||
completetime: 2
|
||||
materials:
|
||||
Steel: 200
|
||||
Plastic: 200
|
||||
|
||||
- type: latheRecipe
|
||||
id: PowerDrill
|
||||
result: PowerDrill
|
||||
|
||||
@@ -194,8 +194,6 @@
|
||||
- Item
|
||||
permanentComponents:
|
||||
- type: TilePrying
|
||||
- type: SignalLinker
|
||||
requiredQuality: Pulsing
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.SignalLinkerUiKey.Key
|
||||
@@ -206,6 +204,9 @@
|
||||
- Screwing
|
||||
speed: 2 # Very powerful multitool to balance out the desire to sell or scrap for points
|
||||
useSound: /Audio/Items/drill_use.ogg
|
||||
- type: Tag
|
||||
tags:
|
||||
- Multitool
|
||||
- type: MultipleTool
|
||||
statusShowBehavior: true
|
||||
entries:
|
||||
|
||||
@@ -498,6 +498,9 @@
|
||||
- type: Tag
|
||||
id: Mop
|
||||
|
||||
- type: Tag
|
||||
id: Multitool
|
||||
|
||||
- type: Tag
|
||||
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