Machine Linking Overhaul (#7160)
This commit is contained in:
@@ -34,7 +34,7 @@ namespace Content.Client.Conveyor.Visualizers
|
|||||||
{
|
{
|
||||||
ConveyorState.Off => _stateStopped,
|
ConveyorState.Off => _stateStopped,
|
||||||
ConveyorState.Forward => _stateRunning,
|
ConveyorState.Forward => _stateRunning,
|
||||||
ConveyorState.Reversed => _stateReversed,
|
ConveyorState.Reverse => _stateReversed,
|
||||||
_ => throw new ArgumentOutOfRangeException()
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -27,13 +27,13 @@ namespace Content.Client.Conveyor.Visualizers
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
appearance.TryGetData(TwoWayLeverVisuals.State, out TwoWayLeverSignal state);
|
appearance.TryGetData(TwoWayLeverVisuals.State, out TwoWayLeverState state);
|
||||||
|
|
||||||
var texture = state switch
|
var texture = state switch
|
||||||
{
|
{
|
||||||
TwoWayLeverSignal.Middle => _stateOff,
|
TwoWayLeverState.Middle => _stateOff,
|
||||||
TwoWayLeverSignal.Right => _stateForward,
|
TwoWayLeverState.Right => _stateForward,
|
||||||
TwoWayLeverSignal.Left => _stateReversed,
|
TwoWayLeverState.Left => _stateReversed,
|
||||||
_ => _stateOff
|
_ => _stateOff
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -275,12 +275,12 @@ namespace Content.Client.Entry
|
|||||||
"Uplink",
|
"Uplink",
|
||||||
"SpawnItemsOnUse",
|
"SpawnItemsOnUse",
|
||||||
"AmbientOnPowered",
|
"AmbientOnPowered",
|
||||||
|
"DoorSignalControl",
|
||||||
"Wieldable",
|
"Wieldable",
|
||||||
"IncreaseDamageOnWield",
|
"IncreaseDamageOnWield",
|
||||||
"TabletopGame",
|
"TabletopGame",
|
||||||
"LitOnPowered",
|
"LitOnPowered",
|
||||||
"TriggerOnSignalReceived",
|
"TriggerOnSignalReceived",
|
||||||
"ToggleDoorOnTrigger",
|
|
||||||
"DeviceNetworkComponent",
|
"DeviceNetworkComponent",
|
||||||
"WiredNetworkConnection",
|
"WiredNetworkConnection",
|
||||||
"WirelessNetworkConnection",
|
"WirelessNetworkConnection",
|
||||||
|
|||||||
@@ -9,9 +9,10 @@ namespace Content.Client.MachineLinking.UI
|
|||||||
{
|
{
|
||||||
private SignalPortSelectorMenu? _menu;
|
private SignalPortSelectorMenu? _menu;
|
||||||
|
|
||||||
public SignalPortSelectorBoundUserInterface([NotNull] ClientUserInterfaceComponent owner, [NotNull] object uiKey) : base(owner, uiKey)
|
private string? _selectedTransmitterPort;
|
||||||
{
|
private string? _selectedReceiverPort;
|
||||||
}
|
|
||||||
|
public SignalPortSelectorBoundUserInterface([NotNull] ClientUserInterfaceComponent owner, [NotNull] object uiKey) : base(owner, uiKey) { }
|
||||||
|
|
||||||
protected override void Open()
|
protected override void Open()
|
||||||
{
|
{
|
||||||
@@ -29,13 +30,46 @@ namespace Content.Client.MachineLinking.UI
|
|||||||
{
|
{
|
||||||
case SignalPortsState data:
|
case SignalPortsState data:
|
||||||
_menu?.UpdateState(data);
|
_menu?.UpdateState(data);
|
||||||
|
_selectedTransmitterPort = null;
|
||||||
|
_selectedReceiverPort = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnPortSelected(string port)
|
public void OnTransmitterPortSelected(string port)
|
||||||
{
|
{
|
||||||
SendMessage(new SignalPortSelected(port));
|
_selectedTransmitterPort = port;
|
||||||
|
if (_selectedReceiverPort != null)
|
||||||
|
{
|
||||||
|
SendMessage(new SignalPortSelected(_selectedTransmitterPort, _selectedReceiverPort));
|
||||||
|
_selectedTransmitterPort = null;
|
||||||
|
_selectedReceiverPort = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnReceiverPortSelected(string port)
|
||||||
|
{
|
||||||
|
_selectedReceiverPort = port;
|
||||||
|
if (_selectedTransmitterPort != null)
|
||||||
|
{
|
||||||
|
SendMessage(new SignalPortSelected(_selectedTransmitterPort, _selectedReceiverPort));
|
||||||
|
_selectedTransmitterPort = null;
|
||||||
|
_selectedReceiverPort = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClearPressed()
|
||||||
|
{
|
||||||
|
_selectedTransmitterPort = null;
|
||||||
|
_selectedReceiverPort = null;
|
||||||
|
SendMessage(new LinkerClearSelected());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnLinkDefaultPressed()
|
||||||
|
{
|
||||||
|
_selectedTransmitterPort = null;
|
||||||
|
_selectedReceiverPort = null;
|
||||||
|
SendMessage(new LinkerLinkDefaultSelected());
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void Dispose(bool disposing)
|
protected override void Dispose(bool disposing)
|
||||||
|
|||||||
@@ -1,4 +1,19 @@
|
|||||||
<customControls:DefaultWindow xmlns:customControls="https://spacestation14.io"
|
<DefaultWindow xmlns="https://spacestation14.io" Title="Port Selector" MinSize="400 200">
|
||||||
Title="Port Selector" MinSize="200 200">
|
<BoxContainer Orientation="Vertical" VerticalExpand="True">
|
||||||
<customControls:ItemList Name="ButtonContainer" VerticalExpand="True" HorizontalExpand="True" SelectMode="Button"/>
|
<BoxContainer Orientation="Horizontal" HorizontalExpand="True" VerticalExpand="True">
|
||||||
</customControls:DefaultWindow>
|
<BoxContainer Orientation="Vertical" HorizontalExpand="True" SizeFlagsStretchRatio="0.3">
|
||||||
|
<RichTextLabel Name="HeaderLeft"/>
|
||||||
|
<BoxContainer Name="ButtonContainerLeft" Orientation="Vertical" VerticalExpand="True" HorizontalExpand="True"/>
|
||||||
|
</BoxContainer>
|
||||||
|
<BoxContainer Name="ContainerMiddle" Orientation="Vertical" HorizontalExpand="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>
|
||||||
|
<BoxContainer Orientation="Horizontal" HorizontalExpand="True">
|
||||||
|
<Button Name="ButtonClear" Text="Clear"/>
|
||||||
|
<Button Name="ButtonLinkDefault" Text="Link Defaults"/>
|
||||||
|
</BoxContainer>
|
||||||
|
</BoxContainer>
|
||||||
|
</DefaultWindow>
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using Content.Shared.MachineLinking;
|
using Content.Shared.MachineLinking;
|
||||||
using Robust.Client.AutoGenerated;
|
using Robust.Client.AutoGenerated;
|
||||||
|
using Robust.Client.UserInterface;
|
||||||
using Robust.Client.UserInterface.Controls;
|
using Robust.Client.UserInterface.Controls;
|
||||||
using Robust.Client.UserInterface.CustomControls;
|
using Robust.Client.UserInterface.CustomControls;
|
||||||
using Robust.Client.UserInterface.XAML;
|
using Robust.Client.UserInterface.XAML;
|
||||||
|
using Robust.Client.Graphics;
|
||||||
|
|
||||||
namespace Content.Client.MachineLinking.UI
|
namespace Content.Client.MachineLinking.UI
|
||||||
{
|
{
|
||||||
@@ -11,25 +12,67 @@ namespace Content.Client.MachineLinking.UI
|
|||||||
public sealed partial class SignalPortSelectorMenu : DefaultWindow
|
public sealed partial class SignalPortSelectorMenu : DefaultWindow
|
||||||
{
|
{
|
||||||
private SignalPortSelectorBoundUserInterface _bui;
|
private SignalPortSelectorBoundUserInterface _bui;
|
||||||
|
private LinksRender links;
|
||||||
|
|
||||||
|
private ButtonGroup buttonGroup = new();
|
||||||
|
|
||||||
public SignalPortSelectorMenu(SignalPortSelectorBoundUserInterface boundUserInterface)
|
public SignalPortSelectorMenu(SignalPortSelectorBoundUserInterface boundUserInterface)
|
||||||
{
|
{
|
||||||
RobustXamlLoader.Load(this);
|
RobustXamlLoader.Load(this);
|
||||||
_bui = boundUserInterface;
|
_bui = boundUserInterface;
|
||||||
|
links = new(ButtonContainerLeft, ButtonContainerRight);
|
||||||
|
ContainerMiddle.AddChild(links);
|
||||||
|
ButtonClear.OnPressed += _ => _bui.OnClearPressed();
|
||||||
|
ButtonLinkDefault.OnPressed += _ => _bui.OnLinkDefaultPressed();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateState(SignalPortsState state)
|
public void UpdateState(SignalPortsState state)
|
||||||
{
|
{
|
||||||
ButtonContainer.Clear();
|
HeaderLeft.SetMessage(state.TransmitterName);
|
||||||
foreach (var port in state.Ports)
|
ButtonContainerLeft.DisposeAllChildren();
|
||||||
|
foreach (var port in state.TransmitterPorts)
|
||||||
{
|
{
|
||||||
var portBtn = new ItemList.Item(ButtonContainer)
|
var portButton = new Button() { Text = port, ToggleMode = true, Group = buttonGroup };
|
||||||
|
portButton.OnPressed += _ => _bui.OnTransmitterPortSelected(port);
|
||||||
|
ButtonContainerLeft.AddChild(portButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
HeaderRight.SetMessage(state.ReceiverName);
|
||||||
|
ButtonContainerRight.DisposeAllChildren();
|
||||||
|
foreach (var port in state.ReceiverPorts)
|
||||||
|
{
|
||||||
|
var portButton = new Button() { Text = port, ToggleMode = true, Group = buttonGroup };
|
||||||
|
portButton.OnPressed += _ => _bui.OnReceiverPortSelected(port);
|
||||||
|
ButtonContainerRight.AddChild(portButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
links.Links = state.Links;
|
||||||
|
}
|
||||||
|
|
||||||
|
private sealed class LinksRender : Control
|
||||||
|
{
|
||||||
|
public List<(int, int)> Links = new();
|
||||||
|
public BoxContainer LeftButton;
|
||||||
|
public BoxContainer RightButton;
|
||||||
|
|
||||||
|
public LinksRender(BoxContainer leftButton, BoxContainer rightButton)
|
||||||
|
{
|
||||||
|
LeftButton = leftButton;
|
||||||
|
RightButton = rightButton;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Draw(DrawingHandleScreen handle)
|
||||||
|
{
|
||||||
|
var leftOffset = LeftButton.PixelPosition.Y;
|
||||||
|
var rightOffset = RightButton.PixelPosition.Y;
|
||||||
|
foreach (var (left, right) in Links)
|
||||||
{
|
{
|
||||||
Text = port.Key,
|
var leftChild = LeftButton.GetChild(left);
|
||||||
Disabled = !port.Value
|
var rightChild = RightButton.GetChild(right);
|
||||||
};
|
var y1 = leftChild.PixelPosition.Y + leftChild.PixelHeight / 2 + leftOffset;
|
||||||
portBtn.OnSelected += _ => _bui.OnPortSelected(port.Key);
|
var y2 = rightChild.PixelPosition.Y + rightChild.PixelHeight / 2 + rightOffset;
|
||||||
ButtonContainer.Add(portBtn);
|
handle.DrawLine((0, y1), (PixelWidth, y2), Color.Cyan);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,16 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using Content.Server.MachineLinking.Components;
|
||||||
using Content.Server.MachineLinking.Events;
|
using Content.Server.MachineLinking.Events;
|
||||||
using Content.Server.MachineLinking.Models;
|
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Server.Recycling;
|
using Content.Server.Recycling;
|
||||||
using Content.Server.Recycling.Components;
|
using Content.Server.Recycling.Components;
|
||||||
using Content.Server.Stunnable;
|
|
||||||
using Content.Shared.Conveyor;
|
using Content.Shared.Conveyor;
|
||||||
using Content.Shared.Item;
|
using Content.Shared.Item;
|
||||||
using Content.Shared.MachineLinking;
|
|
||||||
using Content.Shared.Movement.Components;
|
using Content.Shared.Movement.Components;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Robust.Shared.Containers;
|
using Robust.Shared.Containers;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
|
||||||
using Robust.Shared.Localization;
|
using Robust.Shared.Localization;
|
||||||
using Robust.Shared.Maths;
|
using Robust.Shared.Maths;
|
||||||
using Robust.Shared.Physics;
|
using Robust.Shared.Physics;
|
||||||
@@ -23,18 +20,24 @@ namespace Content.Server.Conveyor
|
|||||||
public sealed class ConveyorSystem : EntitySystem
|
public sealed class ConveyorSystem : EntitySystem
|
||||||
{
|
{
|
||||||
[Dependency] private RecyclerSystem _recycler = default!;
|
[Dependency] private RecyclerSystem _recycler = default!;
|
||||||
[Dependency] private StunSystem _stunSystem = default!;
|
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<ConveyorComponent, ComponentInit>(OnInit);
|
||||||
SubscribeLocalEvent<ConveyorComponent, SignalReceivedEvent>(OnSignalReceived);
|
SubscribeLocalEvent<ConveyorComponent, SignalReceivedEvent>(OnSignalReceived);
|
||||||
SubscribeLocalEvent<ConveyorComponent, PortDisconnectedEvent>(OnPortDisconnected);
|
|
||||||
SubscribeLocalEvent<ConveyorComponent, LinkAttemptEvent>(OnLinkAttempt);
|
|
||||||
SubscribeLocalEvent<ConveyorComponent, PowerChangedEvent>(OnPowerChanged);
|
SubscribeLocalEvent<ConveyorComponent, PowerChangedEvent>(OnPowerChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnInit(EntityUid uid, ConveyorComponent component, ComponentInit args)
|
||||||
|
{
|
||||||
|
var receiver = EnsureComp<SignalReceiverComponent>(uid);
|
||||||
|
foreach (string port in Enum.GetNames<ConveyorState>())
|
||||||
|
if (!receiver.Inputs.ContainsKey(port))
|
||||||
|
receiver.AddPort(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private void OnPowerChanged(EntityUid uid, ConveyorComponent component, PowerChangedEvent args)
|
private void OnPowerChanged(EntityUid uid, ConveyorComponent component, PowerChangedEvent args)
|
||||||
{
|
{
|
||||||
UpdateAppearance(component);
|
UpdateAppearance(component);
|
||||||
@@ -55,41 +58,15 @@ namespace Content.Server.Conveyor
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnLinkAttempt(EntityUid uid, ConveyorComponent component, LinkAttemptEvent args)
|
|
||||||
{
|
|
||||||
if (args.TransmitterComponent.Outputs.GetPort(args.TransmitterPort).Signal is TwoWayLeverSignal signal &&
|
|
||||||
signal != TwoWayLeverSignal.Middle)
|
|
||||||
{
|
|
||||||
args.Cancel();
|
|
||||||
_stunSystem.TryParalyze(uid, TimeSpan.FromSeconds(2f), true);
|
|
||||||
component.Owner.PopupMessage(args.Attemptee, Loc.GetString("conveyor-component-failed-link"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnPortDisconnected(EntityUid uid, ConveyorComponent component, PortDisconnectedEvent args)
|
|
||||||
{
|
|
||||||
SetState(component, TwoWayLeverSignal.Middle);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSignalReceived(EntityUid uid, ConveyorComponent component, SignalReceivedEvent args)
|
private void OnSignalReceived(EntityUid uid, ConveyorComponent component, SignalReceivedEvent args)
|
||||||
{
|
{
|
||||||
switch (args.Port)
|
if (Enum.TryParse(args.Port, out ConveyorState state))
|
||||||
{
|
SetState(component, state);
|
||||||
case "state":
|
|
||||||
SetState(component, (TwoWayLeverSignal) args.Value!);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetState(ConveyorComponent component, TwoWayLeverSignal signal)
|
private void SetState(ConveyorComponent component, ConveyorState state)
|
||||||
{
|
{
|
||||||
component.State = signal switch
|
component.State = state;
|
||||||
{
|
|
||||||
TwoWayLeverSignal.Left => ConveyorState.Reversed,
|
|
||||||
TwoWayLeverSignal.Middle => ConveyorState.Off,
|
|
||||||
TwoWayLeverSignal.Right => ConveyorState.Forward,
|
|
||||||
_ => ConveyorState.Off
|
|
||||||
};
|
|
||||||
|
|
||||||
if (TryComp<RecyclerComponent>(component.Owner, out var recycler))
|
if (TryComp<RecyclerComponent>(component.Owner, out var recycler))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
using Robust.Shared.GameObjects;
|
|
||||||
|
|
||||||
namespace Content.Server.Doors.Components
|
|
||||||
{
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed class ToggleDoorOnTriggerComponent : Component
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -36,7 +36,6 @@ namespace Content.Server.Explosion.EntitySystems
|
|||||||
[Dependency] private readonly ExplosionSystem _explosions = default!;
|
[Dependency] private readonly ExplosionSystem _explosions = default!;
|
||||||
[Dependency] private readonly FixtureSystem _fixtures = default!;
|
[Dependency] private readonly FixtureSystem _fixtures = default!;
|
||||||
[Dependency] private readonly FlashSystem _flashSystem = default!;
|
[Dependency] private readonly FlashSystem _flashSystem = default!;
|
||||||
[Dependency] private readonly DoorSystem _sharedDoorSystem = default!;
|
|
||||||
[Dependency] private readonly SharedBroadphaseSystem _broadphase = default!;
|
[Dependency] private readonly SharedBroadphaseSystem _broadphase = default!;
|
||||||
[Dependency] private readonly AdminLogSystem _logSystem = default!;
|
[Dependency] private readonly AdminLogSystem _logSystem = default!;
|
||||||
|
|
||||||
@@ -52,7 +51,6 @@ namespace Content.Server.Explosion.EntitySystems
|
|||||||
SubscribeLocalEvent<DeleteOnTriggerComponent, TriggerEvent>(HandleDeleteTrigger);
|
SubscribeLocalEvent<DeleteOnTriggerComponent, TriggerEvent>(HandleDeleteTrigger);
|
||||||
SubscribeLocalEvent<ExplodeOnTriggerComponent, TriggerEvent>(HandleExplodeTrigger);
|
SubscribeLocalEvent<ExplodeOnTriggerComponent, TriggerEvent>(HandleExplodeTrigger);
|
||||||
SubscribeLocalEvent<FlashOnTriggerComponent, TriggerEvent>(HandleFlashTrigger);
|
SubscribeLocalEvent<FlashOnTriggerComponent, TriggerEvent>(HandleFlashTrigger);
|
||||||
SubscribeLocalEvent<ToggleDoorOnTriggerComponent, TriggerEvent>(HandleDoorTrigger);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleExplodeTrigger(EntityUid uid, ExplodeOnTriggerComponent component, TriggerEvent args)
|
private void HandleExplodeTrigger(EntityUid uid, ExplodeOnTriggerComponent component, TriggerEvent args)
|
||||||
@@ -73,11 +71,6 @@ namespace Content.Server.Explosion.EntitySystems
|
|||||||
EntityManager.QueueDeleteEntity(uid);
|
EntityManager.QueueDeleteEntity(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleDoorTrigger(EntityUid uid, ToggleDoorOnTriggerComponent component, TriggerEvent args)
|
|
||||||
{
|
|
||||||
_sharedDoorSystem.TryToggleDoor(uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTriggerCollide(EntityUid uid, TriggerOnCollideComponent component, StartCollideEvent args)
|
private void OnTriggerCollide(EntityUid uid, TriggerOnCollideComponent component, StartCollideEvent args)
|
||||||
{
|
{
|
||||||
Trigger(component.Owner);
|
Trigger(component.Owner);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using Content.Server.DeviceNetwork.Systems;
|
|||||||
using Content.Server.Ghost;
|
using Content.Server.Ghost;
|
||||||
using Content.Server.Light.Components;
|
using Content.Server.Light.Components;
|
||||||
using Content.Server.MachineLinking.Events;
|
using Content.Server.MachineLinking.Events;
|
||||||
|
using Content.Server.MachineLinking.Components;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Server.Temperature.Components;
|
using Content.Server.Temperature.Components;
|
||||||
using Content.Shared.Audio;
|
using Content.Shared.Audio;
|
||||||
@@ -58,6 +59,11 @@ namespace Content.Server.Light.EntitySystems
|
|||||||
private void OnInit(EntityUid uid, PoweredLightComponent light, ComponentInit args)
|
private void OnInit(EntityUid uid, PoweredLightComponent light, ComponentInit args)
|
||||||
{
|
{
|
||||||
light.LightBulbContainer = light.Owner.EnsureContainer<ContainerSlot>("light_bulb");
|
light.LightBulbContainer = light.Owner.EnsureContainer<ContainerSlot>("light_bulb");
|
||||||
|
|
||||||
|
var receiver = EnsureComp<SignalReceiverComponent>(uid);
|
||||||
|
foreach (string port in new[] { "On", "Off", "Toggle" })
|
||||||
|
if (!receiver.Inputs.ContainsKey(port))
|
||||||
|
receiver.AddPort(port);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnMapInit(EntityUid uid, PoweredLightComponent light, MapInitEvent args)
|
private void OnMapInit(EntityUid uid, PoweredLightComponent light, MapInitEvent args)
|
||||||
@@ -161,7 +167,7 @@ namespace Content.Server.Light.EntitySystems
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
// check if light has bulb
|
// check if light has bulb
|
||||||
if (GetBulb(uid, light) is not {Valid: true} bulb)
|
if (GetBulb(uid, light) is not { Valid: true } bulb)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// try to remove bulb from container
|
// try to remove bulb from container
|
||||||
@@ -330,16 +336,16 @@ namespace Content.Server.Light.EntitySystems
|
|||||||
{
|
{
|
||||||
switch (args.Port)
|
switch (args.Port)
|
||||||
{
|
{
|
||||||
case "state":
|
case "On": SetState(uid, true, component); break;
|
||||||
ToggleLight(uid, component);
|
case "Off": SetState(uid, false, component); break;
|
||||||
break;
|
case "Toggle": ToggleLight(uid, component); break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Turns the light on or of when receiving a <see cref="DeviceNetworkConstants.CmdSetState"/> command.
|
/// Turns the light on or of when receiving a <see cref="DeviceNetworkConstants.CmdSetState"/> command.
|
||||||
/// The light is turned on or of according to the <see cref="DeviceNetworkConstants.StateEnabled"/> value
|
/// The light is turned on or of according to the <see cref="DeviceNetworkConstants.StateEnabled"/> value
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void OnPacketReceived(EntityUid uid, PoweredLightComponent component, PacketSentEvent args)
|
private void OnPacketReceived(EntityUid uid, PoweredLightComponent component, PacketSentEvent args)
|
||||||
{
|
{
|
||||||
if (!args.Data.TryGetValue(DeviceNetworkConstants.Command, out string? command) || command != DeviceNetworkConstants.CmdSetState) return;
|
if (!args.Data.TryGetValue(DeviceNetworkConstants.Command, out string? command) || command != DeviceNetworkConstants.CmdSetState) return;
|
||||||
@@ -348,7 +354,7 @@ namespace Content.Server.Light.EntitySystems
|
|||||||
SetState(uid, enabled, component);
|
SetState(uid, enabled, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void SetLight(EntityUid uid, bool value, Color? color = null, PoweredLightComponent? light = null, float? radius = null, float? energy = null, float? softness=null)
|
private void SetLight(EntityUid uid, bool value, Color? color = null, PoweredLightComponent? light = null, float? radius = null, float? energy = null, float? softness = null)
|
||||||
{
|
{
|
||||||
if (!Resolve(uid, ref light))
|
if (!Resolve(uid, ref light))
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
|
||||||
|
namespace Content.Server.MachineLinking.Components
|
||||||
|
{
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class DoorSignalControlComponent : Component
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,9 @@ namespace Content.Server.MachineLinking.Components
|
|||||||
public sealed class SignalLinkerComponent : Component
|
public sealed class SignalLinkerComponent : Component
|
||||||
{
|
{
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public (SignalTransmitterComponent transmitter, string port)? Port;
|
public EntityUid? savedTransmitter;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
public EntityUid? savedReceiver;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Content.Server.MachineLinking.Models;
|
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Serialization.Manager.Attributes;
|
using Robust.Shared.Serialization.Manager.Attributes;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
@@ -11,9 +10,14 @@ namespace Content.Server.MachineLinking.Components
|
|||||||
public sealed class SignalReceiverComponent : Component
|
public sealed class SignalReceiverComponent : Component
|
||||||
{
|
{
|
||||||
[DataField("inputs")]
|
[DataField("inputs")]
|
||||||
private List<SignalPort> _inputs = new();
|
private Dictionary<string, List<PortIdentifier>> _inputs = new();
|
||||||
|
|
||||||
|
public void AddPort(string name)
|
||||||
|
{
|
||||||
|
_inputs.Add(name, new());
|
||||||
|
}
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public IReadOnlyList<SignalPort> Inputs => _inputs;
|
public IReadOnlyDictionary<string, List<PortIdentifier>> Inputs => _inputs;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,48 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Content.Server.MachineLinking.Models;
|
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.Serialization.Manager.Attributes;
|
using Robust.Shared.Serialization.Manager.Attributes;
|
||||||
using Robust.Shared.ViewVariables;
|
using Robust.Shared.ViewVariables;
|
||||||
|
using Content.Server.MachineLinking.System;
|
||||||
|
|
||||||
namespace Content.Server.MachineLinking.Components
|
namespace Content.Server.MachineLinking.Components
|
||||||
{
|
{
|
||||||
|
[DataDefinition]
|
||||||
|
public struct PortIdentifier
|
||||||
|
{
|
||||||
|
[DataField("uid")]
|
||||||
|
public EntityUid Uid;
|
||||||
|
|
||||||
|
[DataField("port")]
|
||||||
|
public string Port;
|
||||||
|
|
||||||
|
public PortIdentifier(EntityUid uid, string port)
|
||||||
|
{
|
||||||
|
Uid = uid;
|
||||||
|
Port = port;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed class SignalTransmitterComponent : Component
|
public sealed class SignalTransmitterComponent : Component
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// How far the device can transmit a signal wirelessly.
|
||||||
|
/// Devices farther than this range can still transmit if they are
|
||||||
|
/// on the same powernet.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("transmissionRange")]
|
||||||
|
public float TransmissionRange = 30f;
|
||||||
|
|
||||||
[DataField("outputs")]
|
[DataField("outputs")]
|
||||||
private List<SignalPort> _outputs = new();
|
private Dictionary<string, List<PortIdentifier>> _outputs = new();
|
||||||
|
|
||||||
[ViewVariables]
|
[ViewVariables]
|
||||||
public IReadOnlyList<SignalPort> Outputs => _outputs;
|
public IReadOnlyDictionary<string, List<PortIdentifier>> Outputs => _outputs;
|
||||||
|
|
||||||
|
public void AddPort(string name)
|
||||||
|
{
|
||||||
|
_outputs.Add(name, new());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ namespace Content.Server.MachineLinking.Components
|
|||||||
[RegisterComponent]
|
[RegisterComponent]
|
||||||
public sealed class TwoWayLeverComponent : Component
|
public sealed class TwoWayLeverComponent : Component
|
||||||
{
|
{
|
||||||
public TwoWayLeverSignal State;
|
public TwoWayLeverState State;
|
||||||
|
|
||||||
public bool NextSignalLeft;
|
public bool NextSignalLeft;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,10 @@ namespace Content.Server.MachineLinking.Events
|
|||||||
public sealed class InvokePortEvent : EntityEventArgs
|
public sealed class InvokePortEvent : EntityEventArgs
|
||||||
{
|
{
|
||||||
public readonly string Port;
|
public readonly string Port;
|
||||||
public readonly object? Value;
|
|
||||||
|
|
||||||
public InvokePortEvent(string port, object? value = null)
|
public InvokePortEvent(string port)
|
||||||
{
|
{
|
||||||
Port = port;
|
Port = port;
|
||||||
Value = value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,19 +5,17 @@ namespace Content.Server.MachineLinking.Events
|
|||||||
{
|
{
|
||||||
public sealed class LinkAttemptEvent : CancellableEntityEventArgs
|
public sealed class LinkAttemptEvent : CancellableEntityEventArgs
|
||||||
{
|
{
|
||||||
public readonly EntityUid Attemptee;
|
|
||||||
public readonly SignalTransmitterComponent TransmitterComponent;
|
public readonly SignalTransmitterComponent TransmitterComponent;
|
||||||
public readonly string TransmitterPort;
|
public readonly string TransmitterPort;
|
||||||
public readonly SignalReceiverComponent ReceiverComponent;
|
public readonly SignalReceiverComponent ReceiverComponent;
|
||||||
public readonly string ReceiverPort;
|
public readonly string ReceiverPort;
|
||||||
|
|
||||||
public LinkAttemptEvent(EntityUid attemptee, SignalTransmitterComponent transmitterComponent, string transmitterPort, SignalReceiverComponent receiverComponent, string receiverPort)
|
public LinkAttemptEvent(SignalTransmitterComponent transmitterComponent, string transmitterPort, SignalReceiverComponent receiverComponent, string receiverPort)
|
||||||
{
|
{
|
||||||
TransmitterComponent = transmitterComponent;
|
TransmitterComponent = transmitterComponent;
|
||||||
this.TransmitterPort = transmitterPort;
|
this.TransmitterPort = transmitterPort;
|
||||||
ReceiverComponent = receiverComponent;
|
ReceiverComponent = receiverComponent;
|
||||||
this.ReceiverPort = receiverPort;
|
this.ReceiverPort = receiverPort;
|
||||||
Attemptee = attemptee;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,12 +5,10 @@ namespace Content.Server.MachineLinking.Events
|
|||||||
public sealed class SignalReceivedEvent : EntityEventArgs
|
public sealed class SignalReceivedEvent : EntityEventArgs
|
||||||
{
|
{
|
||||||
public readonly string Port;
|
public readonly string Port;
|
||||||
public readonly object? Value;
|
|
||||||
|
|
||||||
public SignalReceivedEvent(string port, object? value)
|
public SignalReceivedEvent(string port)
|
||||||
{
|
{
|
||||||
Port = port;
|
Port = port;
|
||||||
Value = value;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
|
|
||||||
namespace Content.Server.MachineLinking.Events
|
|
||||||
{
|
|
||||||
public sealed class SignalValueRequestedEvent : HandledEntityEventArgs
|
|
||||||
{
|
|
||||||
public readonly string Port;
|
|
||||||
public readonly Type Type;
|
|
||||||
|
|
||||||
public object? Signal;
|
|
||||||
|
|
||||||
public SignalValueRequestedEvent(string port, Type type)
|
|
||||||
{
|
|
||||||
Port = port;
|
|
||||||
Type = type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
using Content.Server.MachineLinking.Components;
|
|
||||||
|
|
||||||
namespace Content.Server.MachineLinking.Models
|
|
||||||
{
|
|
||||||
public sealed class SignalLink
|
|
||||||
{
|
|
||||||
public readonly SignalTransmitterComponent TransmitterComponent;
|
|
||||||
public readonly SignalReceiverComponent ReceiverComponent;
|
|
||||||
public readonly SignalPort Transmitterport;
|
|
||||||
public readonly SignalPort Receiverport;
|
|
||||||
|
|
||||||
public SignalLink(SignalTransmitterComponent transmitterComponent, string transmitterPort, SignalReceiverComponent receiverComponent, string receiverPort)
|
|
||||||
{
|
|
||||||
TransmitterComponent = transmitterComponent;
|
|
||||||
ReceiverComponent = receiverComponent;
|
|
||||||
Transmitterport = TransmitterComponent.Outputs.GetPort(transmitterPort);
|
|
||||||
Receiverport = ReceiverComponent.Inputs.GetPort(receiverPort);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,131 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using Content.Server.MachineLinking.Components;
|
|
||||||
using Content.Server.MachineLinking.Exceptions;
|
|
||||||
|
|
||||||
namespace Content.Server.MachineLinking.Models
|
|
||||||
{
|
|
||||||
public sealed class SignalLinkCollection
|
|
||||||
{
|
|
||||||
private Dictionary<SignalTransmitterComponent, List<SignalLink>> _transmitterDict = new();
|
|
||||||
private Dictionary<SignalReceiverComponent, List<SignalLink>> _receiverDict = new();
|
|
||||||
|
|
||||||
public SignalLink AddLink(SignalTransmitterComponent transmitterComponent, string transmitterPort,
|
|
||||||
SignalReceiverComponent receiverComponent, string receiverPort)
|
|
||||||
{
|
|
||||||
if (LinkExists(transmitterComponent, transmitterPort, receiverComponent, receiverPort))
|
|
||||||
{
|
|
||||||
throw new LinkAlreadyRegisteredException();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_transmitterDict.ContainsKey(transmitterComponent))
|
|
||||||
{
|
|
||||||
_transmitterDict[transmitterComponent] = new();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_receiverDict.ContainsKey(receiverComponent))
|
|
||||||
{
|
|
||||||
_receiverDict[receiverComponent] = new();
|
|
||||||
}
|
|
||||||
|
|
||||||
var link = new SignalLink(transmitterComponent, transmitterPort, receiverComponent, receiverPort);
|
|
||||||
_transmitterDict[transmitterComponent].Add(link);
|
|
||||||
_receiverDict[receiverComponent].Add(link);
|
|
||||||
|
|
||||||
return link;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool LinkExists(SignalTransmitterComponent transmitterComponent, string transmitterPort,
|
|
||||||
SignalReceiverComponent receiverComponent, string receiverPort)
|
|
||||||
{
|
|
||||||
if (!_transmitterDict.ContainsKey(transmitterComponent) || !_receiverDict.ContainsKey(receiverComponent))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var link in _transmitterDict[transmitterComponent])
|
|
||||||
{
|
|
||||||
if (link.Transmitterport.Name == transmitterPort && link.Receiverport.Name == receiverPort &&
|
|
||||||
link.ReceiverComponent == receiverComponent)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool RemoveLink(SignalTransmitterComponent transmitterComponent, string transmitterPort,
|
|
||||||
SignalReceiverComponent receiverComponent, string receiverPort)
|
|
||||||
{
|
|
||||||
if (!_transmitterDict.ContainsKey(transmitterComponent) || !_receiverDict.ContainsKey(receiverComponent))
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
SignalLink? theLink = null;
|
|
||||||
foreach (var link in _transmitterDict[transmitterComponent])
|
|
||||||
{
|
|
||||||
if (link.Transmitterport.Name == transmitterPort && link.Receiverport.Name == receiverPort &&
|
|
||||||
link.ReceiverComponent == receiverComponent)
|
|
||||||
{
|
|
||||||
theLink = link;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (theLink == null) return false;
|
|
||||||
|
|
||||||
_transmitterDict[transmitterComponent].Remove(theLink);
|
|
||||||
if (_transmitterDict[transmitterComponent].Count == 0) _transmitterDict.Remove(transmitterComponent);
|
|
||||||
_receiverDict[receiverComponent].Remove(theLink);
|
|
||||||
if (_receiverDict[receiverComponent].Count == 0) _receiverDict.Remove(receiverComponent);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int LinkCount(SignalTransmitterComponent comp) =>
|
|
||||||
_transmitterDict.ContainsKey(comp) ? _transmitterDict[comp].Count : 0;
|
|
||||||
|
|
||||||
public int LinkCount(SignalReceiverComponent comp) =>
|
|
||||||
_receiverDict.ContainsKey(comp) ? _receiverDict[comp].Count : 0;
|
|
||||||
|
|
||||||
public void RemoveLinks(SignalTransmitterComponent component)
|
|
||||||
{
|
|
||||||
if (!_transmitterDict.ContainsKey(component))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var link in _transmitterDict[component])
|
|
||||||
{
|
|
||||||
_receiverDict[link.ReceiverComponent].Remove(link);
|
|
||||||
if (_receiverDict[link.ReceiverComponent].Count == 0) _receiverDict.Remove(link.ReceiverComponent);
|
|
||||||
}
|
|
||||||
|
|
||||||
_transmitterDict.Remove(component);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveLinks(SignalReceiverComponent component)
|
|
||||||
{
|
|
||||||
if (!_receiverDict.ContainsKey(component))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var link in _receiverDict[component])
|
|
||||||
{
|
|
||||||
_transmitterDict[link.TransmitterComponent].Remove(link);
|
|
||||||
if (_transmitterDict[link.TransmitterComponent].Count == 0)
|
|
||||||
_transmitterDict.Remove(link.TransmitterComponent);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public IEnumerable<SignalLink> GetLinks(SignalTransmitterComponent component, string port)
|
|
||||||
{
|
|
||||||
if (!_transmitterDict.ContainsKey(component)) yield break;
|
|
||||||
|
|
||||||
foreach (var link in _transmitterDict[component])
|
|
||||||
{
|
|
||||||
if (link.Transmitterport.Name != port) continue;
|
|
||||||
yield return link;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using Content.Server.MachineLinking.Events;
|
|
||||||
using Content.Server.MachineLinking.Exceptions;
|
|
||||||
using Robust.Shared.Serialization.Manager.Attributes;
|
|
||||||
|
|
||||||
namespace Content.Server.MachineLinking.Models
|
|
||||||
{
|
|
||||||
[DataDefinition]
|
|
||||||
public sealed class SignalPort
|
|
||||||
{
|
|
||||||
[DataField("name", required: true)] public string Name { get; } = default!;
|
|
||||||
[DataField("type")] public Type? Type { get; }
|
|
||||||
/// <summary>
|
|
||||||
/// Maximum connections of the port. 0 means infinite.
|
|
||||||
/// </summary>
|
|
||||||
[DataField("maxConnections")] public int MaxConnections { get; } = 0;
|
|
||||||
|
|
||||||
public object? Signal;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class PortPrototypeExtensions{
|
|
||||||
public static bool ContainsPort(this IReadOnlyList<SignalPort> ports, string port)
|
|
||||||
{
|
|
||||||
foreach (var portPrototype in ports)
|
|
||||||
{
|
|
||||||
if (portPrototype.Name == port)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IEnumerable<string> GetPortStrings(this IReadOnlyList<SignalPort> ports)
|
|
||||||
{
|
|
||||||
foreach (var portPrototype in ports)
|
|
||||||
{
|
|
||||||
yield return portPrototype.Name;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IEnumerable<KeyValuePair<string, bool>> GetValidatedPorts(this IReadOnlyList<SignalPort> ports, Type? validType)
|
|
||||||
{
|
|
||||||
foreach (var portPrototype in ports)
|
|
||||||
{
|
|
||||||
yield return new KeyValuePair<string, bool>(portPrototype.Name, portPrototype.Type == validType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static bool TryGetPort(this IReadOnlyList<SignalPort> ports, string name, [NotNullWhen(true)] out SignalPort? port)
|
|
||||||
{
|
|
||||||
foreach (var portPrototype in ports)
|
|
||||||
{
|
|
||||||
if (portPrototype.Name == name)
|
|
||||||
{
|
|
||||||
port = portPrototype;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
port = null;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static SignalPort GetPort(this IReadOnlyList<SignalPort> ports, string name)
|
|
||||||
{
|
|
||||||
foreach (var portPrototype in ports)
|
|
||||||
{
|
|
||||||
if (portPrototype.Name == name)
|
|
||||||
{
|
|
||||||
return portPrototype;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new PortNotFoundException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
using Content.Server.MachineLinking.Components;
|
||||||
|
using Content.Server.MachineLinking.Events;
|
||||||
|
using Content.Server.Doors.Systems;
|
||||||
|
using Content.Shared.Doors.Components;
|
||||||
|
using Content.Shared.Interaction;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Robust.Shared.GameObjects;
|
||||||
|
|
||||||
|
namespace Content.Server.MachineLinking.System
|
||||||
|
{
|
||||||
|
[UsedImplicitly]
|
||||||
|
public sealed class DoorSignalControlSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly DoorSystem _doorSystem = default!;
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<DoorSignalControlComponent, ComponentInit>(OnInit);
|
||||||
|
SubscribeLocalEvent<DoorSignalControlComponent, SignalReceivedEvent>(OnSignalReceived);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInit(EntityUid uid, DoorSignalControlComponent component, ComponentInit args)
|
||||||
|
{
|
||||||
|
var receiver = EnsureComp<SignalReceiverComponent>(uid);
|
||||||
|
foreach (string port in new[] { "Open", "Close", "Toggle" })
|
||||||
|
if (!receiver.Inputs.ContainsKey(port))
|
||||||
|
receiver.AddPort(port);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSignalReceived(EntityUid uid, DoorSignalControlComponent component, SignalReceivedEvent args)
|
||||||
|
{
|
||||||
|
if (!TryComp(uid, out DoorComponent? door)) return;
|
||||||
|
switch (args.Port)
|
||||||
|
{
|
||||||
|
case "Open": if (door.State != DoorState.Open) _doorSystem.TryOpen(uid, door); break;
|
||||||
|
case "Close": if (door.State != DoorState.Closed) _doorSystem.TryClose(uid, door); break;
|
||||||
|
case "Toggle": _doorSystem.TryToggleDoor(uid); break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -12,13 +12,20 @@ namespace Content.Server.MachineLinking.System
|
|||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<SignalButtonComponent, ComponentInit>(OnInit);
|
||||||
SubscribeLocalEvent<SignalButtonComponent, InteractHandEvent>(OnInteractHand);
|
SubscribeLocalEvent<SignalButtonComponent, InteractHandEvent>(OnInteractHand);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnInit(EntityUid uid, SignalButtonComponent component, ComponentInit args)
|
||||||
|
{
|
||||||
|
var transmitter = EnsureComp<SignalTransmitterComponent>(uid);
|
||||||
|
if (!transmitter.Outputs.ContainsKey("Pressed"))
|
||||||
|
transmitter.AddPort("Pressed");
|
||||||
|
}
|
||||||
|
|
||||||
private void OnInteractHand(EntityUid uid, SignalButtonComponent component, InteractHandEvent args)
|
private void OnInteractHand(EntityUid uid, SignalButtonComponent component, InteractHandEvent args)
|
||||||
{
|
{
|
||||||
RaiseLocalEvent(uid, new InvokePortEvent("pressed"), false);
|
RaiseLocalEvent(uid, new InvokePortEvent("Pressed"), false);
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,293 +1,338 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Hands.Components;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using Content.Server.Interaction;
|
|
||||||
using Content.Server.MachineLinking.Components;
|
using Content.Server.MachineLinking.Components;
|
||||||
using Content.Server.MachineLinking.Events;
|
using Content.Server.MachineLinking.Events;
|
||||||
using Content.Server.MachineLinking.Exceptions;
|
|
||||||
using Content.Server.MachineLinking.Models;
|
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Server.UserInterface;
|
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.MachineLinking;
|
using Content.Shared.MachineLinking;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
using Robust.Shared.GameObjects;
|
|
||||||
using Robust.Shared.Localization;
|
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
using Robust.Shared.Player;
|
||||||
|
|
||||||
namespace Content.Server.MachineLinking.System
|
namespace Content.Server.MachineLinking.System
|
||||||
{
|
{
|
||||||
public sealed class SignalLinkerSystem : EntitySystem
|
public sealed class SignalLinkerSystem : EntitySystem
|
||||||
{
|
{
|
||||||
private InteractionSystem _interaction = default!;
|
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
|
||||||
|
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||||
|
|
||||||
private SignalLinkCollection _linkCollection = new();
|
private static readonly (string, string)[][] _defaultMappings =
|
||||||
|
{
|
||||||
|
new [] { ("Pressed", "Toggle") },
|
||||||
|
new [] { ("On", "On"), ("Off", "Off") },
|
||||||
|
new [] { ("On", "Open"), ("Off", "Close") },
|
||||||
|
new [] { ("On", "Forward"), ("Off", "Off") },
|
||||||
|
new [] { ("Left", "On"), ("Right", "On"), ("Middle", "Off") },
|
||||||
|
new [] { ("Left", "Open"), ("Right", "Open"), ("Middle", "Close") },
|
||||||
|
new [] { ("Left", "Forward"), ("Right", "Reverse"), ("Middle", "Off") },
|
||||||
|
};
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
|
||||||
_interaction = Get<InteractionSystem>();
|
|
||||||
|
|
||||||
SubscribeLocalEvent<SignalTransmitterComponent, ComponentStartup>(TransmitterStartupHandler);
|
|
||||||
SubscribeLocalEvent<SignalTransmitterComponent, InteractUsingEvent>(TransmitterInteractUsingHandler);
|
|
||||||
SubscribeLocalEvent<SignalTransmitterComponent, InvokePortEvent>(OnTransmitterInvokePort);
|
SubscribeLocalEvent<SignalTransmitterComponent, InvokePortEvent>(OnTransmitterInvokePort);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<SignalTransmitterComponent, ComponentStartup>(OnTransmitterStartup);
|
||||||
|
SubscribeLocalEvent<SignalTransmitterComponent, ComponentRemove>(OnTransmitterRemoved);
|
||||||
|
SubscribeLocalEvent<SignalTransmitterComponent, InteractUsingEvent>(OnTransmitterInteractUsing);
|
||||||
|
|
||||||
SubscribeLocalEvent<SignalReceiverComponent, ComponentStartup>(OnReceiverStartup);
|
SubscribeLocalEvent<SignalReceiverComponent, ComponentStartup>(OnReceiverStartup);
|
||||||
|
SubscribeLocalEvent<SignalReceiverComponent, ComponentRemove>(OnReceiverRemoved);
|
||||||
SubscribeLocalEvent<SignalReceiverComponent, InteractUsingEvent>(OnReceiverInteractUsing);
|
SubscribeLocalEvent<SignalReceiverComponent, InteractUsingEvent>(OnReceiverInteractUsing);
|
||||||
|
|
||||||
SubscribeLocalEvent<SignalReceiverComponent, ComponentRemove>(OnReceiverRemoved);
|
SubscribeLocalEvent<SignalLinkerComponent, SignalPortSelected>(OnSignalPortSelected);
|
||||||
SubscribeLocalEvent<SignalTransmitterComponent, ComponentRemove>(OnTransmitterRemoved);
|
SubscribeLocalEvent<SignalLinkerComponent, LinkerClearSelected>(OnLinkerClearSelected);
|
||||||
}
|
SubscribeLocalEvent<SignalLinkerComponent, LinkerLinkDefaultSelected>(OnLinkerLinkDefaultSelected);
|
||||||
|
SubscribeLocalEvent<SignalLinkerComponent, BoundUIClosedEvent>(OnLinkerUIClosed);
|
||||||
private void OnTransmitterRemoved(EntityUid uid, SignalTransmitterComponent component, ComponentRemove args)
|
|
||||||
{
|
|
||||||
_linkCollection.RemoveLinks(component);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnReceiverRemoved(EntityUid uid, SignalReceiverComponent component, ComponentRemove args)
|
|
||||||
{
|
|
||||||
_linkCollection.RemoveLinks(component);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnTransmitterInvokePort(EntityUid uid, SignalTransmitterComponent component, InvokePortEvent args)
|
private void OnTransmitterInvokePort(EntityUid uid, SignalTransmitterComponent component, InvokePortEvent args)
|
||||||
{
|
{
|
||||||
if (!component.Outputs.TryGetPort(args.Port, out var port)) throw new PortNotFoundException();
|
foreach (var receiver in component.Outputs[args.Port])
|
||||||
|
RaiseLocalEvent(receiver.Uid, new SignalReceivedEvent(receiver.Port), false);
|
||||||
if (args.Value == null)
|
|
||||||
{
|
|
||||||
if (port.Type != null && !port.Type.IsNullable()) throw new InvalidPortValueException();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (port.Type == null || !args.Value.GetType().IsAssignableTo(port.Type))
|
|
||||||
throw new InvalidPortValueException();
|
|
||||||
}
|
|
||||||
|
|
||||||
port.Signal = args.Value;
|
|
||||||
|
|
||||||
foreach (var link in _linkCollection.GetLinks(component, port.Name))
|
|
||||||
{
|
|
||||||
if (!IsInRange(component, link.ReceiverComponent)) continue;
|
|
||||||
|
|
||||||
RaiseLocalEvent(link.ReceiverComponent.Owner,
|
|
||||||
new SignalReceivedEvent(link.Receiverport.Name, args.Value), false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnReceiverInteractUsing(EntityUid uid, SignalReceiverComponent component, InteractUsingEvent args)
|
private void OnTransmitterStartup(EntityUid uid, SignalTransmitterComponent transmitter, ComponentStartup args)
|
||||||
|
{
|
||||||
|
// validate links
|
||||||
|
Dictionary<EntityUid, SignalReceiverComponent?> uidCache = new();
|
||||||
|
foreach (var tport in transmitter.Outputs)
|
||||||
|
foreach (var rport in tport.Value)
|
||||||
|
{
|
||||||
|
if (!uidCache.TryGetValue(rport.Uid, out var receiver))
|
||||||
|
uidCache.Add(rport.Uid, receiver = CompOrNull<SignalReceiverComponent>(rport.Uid));
|
||||||
|
if (receiver == null || !receiver.Inputs.TryGetValue(rport.Port, out var rpv))
|
||||||
|
tport.Value.Remove(rport);
|
||||||
|
else if (!rpv.Contains(new(uid, tport.Key)))
|
||||||
|
rpv.Add(new(uid, tport.Key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnReceiverStartup(EntityUid uid, SignalReceiverComponent receiver, ComponentStartup args)
|
||||||
|
{
|
||||||
|
// validate links
|
||||||
|
Dictionary<EntityUid, SignalTransmitterComponent?> uidCache = new();
|
||||||
|
foreach (var rport in receiver.Inputs)
|
||||||
|
foreach (var tport in rport.Value)
|
||||||
|
{
|
||||||
|
if (!uidCache.TryGetValue(tport.Uid, out var transmitter))
|
||||||
|
uidCache.Add(tport.Uid, transmitter = CompOrNull<SignalTransmitterComponent>(tport.Uid));
|
||||||
|
if (transmitter == null || !transmitter.Outputs.TryGetValue(tport.Port, out var tpv))
|
||||||
|
rport.Value.Remove(tport);
|
||||||
|
else if (!tpv.Contains(new(uid, rport.Key)))
|
||||||
|
tpv.Add(new(uid, rport.Key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTransmitterRemoved(EntityUid uid, SignalTransmitterComponent transmitter, ComponentRemove args)
|
||||||
|
{
|
||||||
|
Dictionary<EntityUid, SignalReceiverComponent?> uidCache = new();
|
||||||
|
foreach (var tport in transmitter.Outputs)
|
||||||
|
foreach (var rport in tport.Value)
|
||||||
|
{
|
||||||
|
if (!uidCache.TryGetValue(rport.Uid, out var receiver))
|
||||||
|
uidCache.Add(rport.Uid, receiver = CompOrNull<SignalReceiverComponent>(rport.Uid));
|
||||||
|
if (receiver != null && receiver.Inputs.TryGetValue(rport.Port, out var rpv))
|
||||||
|
rpv.Remove(new(uid, tport.Key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnReceiverRemoved(EntityUid uid, SignalReceiverComponent component, ComponentRemove args)
|
||||||
|
{
|
||||||
|
Dictionary<EntityUid, SignalTransmitterComponent?> uidCache = new();
|
||||||
|
foreach (var rport in component.Inputs)
|
||||||
|
foreach (var tport in rport.Value)
|
||||||
|
{
|
||||||
|
if (!uidCache.TryGetValue(tport.Uid, out var transmitter))
|
||||||
|
uidCache.Add(tport.Uid, transmitter = CompOrNull<SignalTransmitterComponent>(tport.Uid));
|
||||||
|
if (transmitter != null && transmitter.Outputs.TryGetValue(tport.Port, out var receivers))
|
||||||
|
receivers.Remove(new(uid, rport.Key));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnTransmitterInteractUsing(EntityUid uid, SignalTransmitterComponent transmitter, InteractUsingEvent args)
|
||||||
{
|
{
|
||||||
if (args.Handled) return;
|
if (args.Handled) return;
|
||||||
|
|
||||||
if (!EntityManager.TryGetComponent<SignalLinkerComponent?>(args.Used, out var linker) || !linker.Port.HasValue ||
|
if (!TryComp(args.Used, out SignalLinkerComponent? linker) ||
|
||||||
!EntityManager.TryGetComponent(args.User, out ActorComponent? actor) ||
|
!TryComp(args.User, out ActorComponent? actor))
|
||||||
!linker.Port.Value.transmitter.Outputs.TryGetPort(linker.Port.Value.port, out var port))
|
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (component.Inputs.Count == 1)
|
linker.savedTransmitter = uid;
|
||||||
|
|
||||||
|
if (!TryComp(linker.savedReceiver, out SignalReceiverComponent? receiver))
|
||||||
{
|
{
|
||||||
LinkerInteraction(args.User, linker.Port.Value.transmitter, linker.Port.Value.port, component,
|
_popupSystem.PopupCursor(Loc.GetString("signal-linker-component-saved", ("machine", uid)),
|
||||||
component.Inputs[0].Name);
|
Filter.Entities(args.User));
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var bui = component.Owner.GetUIOrNull(SignalReceiverUiKey.Key);
|
if (TryGetOrOpenUI(actor, linker, out var bui))
|
||||||
if (bui == null)
|
|
||||||
{
|
{
|
||||||
|
TryUpdateUI(linker, transmitter, receiver, bui);
|
||||||
|
args.Handled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
bui.Open(actor.PlayerSession);
|
|
||||||
bui.SetState(
|
|
||||||
new SignalPortsState(new Dictionary<string, bool>(component.Inputs.GetValidatedPorts(port.Type))));
|
|
||||||
args.Handled = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnReceiverStartup(EntityUid uid, SignalReceiverComponent component, ComponentStartup args)
|
private void OnReceiverInteractUsing(EntityUid uid, SignalReceiverComponent receiver, InteractUsingEvent args)
|
||||||
{
|
|
||||||
if (component.Owner.GetUIOrNull(SignalReceiverUiKey.Key) is { } ui)
|
|
||||||
ui.OnReceiveMessage += msg => OnReceiverUIMessage(uid, component, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnReceiverUIMessage(EntityUid uid, SignalReceiverComponent component,
|
|
||||||
ServerBoundUserInterfaceMessage msg)
|
|
||||||
{
|
|
||||||
if (msg.Session.AttachedEntity is not { } attached) return;
|
|
||||||
|
|
||||||
switch (msg.Message)
|
|
||||||
{
|
|
||||||
case SignalPortSelected portSelected:
|
|
||||||
if (msg.Session.AttachedEntity == default ||
|
|
||||||
!EntityManager.TryGetComponent(msg.Session.AttachedEntity, out HandsComponent? hands) ||
|
|
||||||
hands.ActiveHandEntity is not EntityUid heldEntity ||
|
|
||||||
!EntityManager.TryGetComponent(heldEntity, out SignalLinkerComponent? signalLinkerComponent) ||
|
|
||||||
!signalLinkerComponent.Port.HasValue ||
|
|
||||||
!signalLinkerComponent.Port.Value.transmitter.Outputs.ContainsPort(signalLinkerComponent.Port
|
|
||||||
.Value.port) || !component.Inputs.ContainsPort(portSelected.Port))
|
|
||||||
return;
|
|
||||||
LinkerInteraction(attached, signalLinkerComponent.Port.Value.transmitter,
|
|
||||||
signalLinkerComponent.Port.Value.port, component, portSelected.Port);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TransmitterStartupHandler(EntityUid uid, SignalTransmitterComponent component,
|
|
||||||
ComponentStartup args)
|
|
||||||
{
|
|
||||||
if (component.Owner.GetUIOrNull(SignalTransmitterUiKey.Key) is { } ui)
|
|
||||||
ui.OnReceiveMessage += msg => OnTransmitterUIMessage(uid, component, msg);
|
|
||||||
|
|
||||||
foreach (var portPrototype in component.Outputs)
|
|
||||||
{
|
|
||||||
if (portPrototype.Type == null) continue;
|
|
||||||
|
|
||||||
var valueRequest = new SignalValueRequestedEvent(portPrototype.Name, portPrototype.Type);
|
|
||||||
RaiseLocalEvent(uid, valueRequest, false);
|
|
||||||
|
|
||||||
if (!valueRequest.Handled) throw new NoSignalValueProvidedException();
|
|
||||||
|
|
||||||
portPrototype.Signal = valueRequest.Signal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnTransmitterUIMessage(EntityUid uid, SignalTransmitterComponent component,
|
|
||||||
ServerBoundUserInterfaceMessage msg)
|
|
||||||
{
|
|
||||||
if (msg.Session.AttachedEntity is not { } attached)
|
|
||||||
return;
|
|
||||||
|
|
||||||
switch (msg.Message)
|
|
||||||
{
|
|
||||||
case SignalPortSelected portSelected:
|
|
||||||
if (msg.Session.AttachedEntity == default ||
|
|
||||||
!EntityManager.TryGetComponent(msg.Session.AttachedEntity, out HandsComponent? hands) ||
|
|
||||||
hands.ActiveHandEntity is not EntityUid heldEntity ||
|
|
||||||
!EntityManager.TryGetComponent(heldEntity, out SignalLinkerComponent? signalLinkerComponent))
|
|
||||||
return;
|
|
||||||
LinkerSaveInteraction(attached, signalLinkerComponent, component,
|
|
||||||
portSelected.Port);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TransmitterInteractUsingHandler(EntityUid uid, SignalTransmitterComponent component,
|
|
||||||
InteractUsingEvent args)
|
|
||||||
{
|
{
|
||||||
if (args.Handled) return;
|
if (args.Handled) return;
|
||||||
|
|
||||||
if (!EntityManager.TryGetComponent<SignalLinkerComponent?>(args.Used, out var linker) ||
|
if (!TryComp(args.Used, out SignalLinkerComponent? linker) ||
|
||||||
!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
|
!TryComp(args.User, out ActorComponent? actor))
|
||||||
{
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (component.Outputs.Count == 1)
|
linker.savedReceiver = uid;
|
||||||
|
|
||||||
|
if (!TryComp(linker.savedTransmitter, out SignalTransmitterComponent? transmitter))
|
||||||
{
|
{
|
||||||
var port = component.Outputs.First();
|
_popupSystem.PopupCursor(Loc.GetString("signal-linker-component-saved", ("machine", uid)),
|
||||||
LinkerSaveInteraction(args.User, linker, component, port.Name);
|
Filter.Entities(args.User));
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var bui = component.Owner.GetUIOrNull(SignalTransmitterUiKey.Key);
|
if (TryGetOrOpenUI(actor, linker, out var bui))
|
||||||
if (bui == null) return;
|
|
||||||
bui.Open(actor.PlayerSession);
|
|
||||||
bui.SetState(new SignalPortsState(component.Outputs.GetPortStrings().ToArray()));
|
|
||||||
args.Handled = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LinkerInteraction(EntityUid entity, SignalTransmitterComponent transmitter, string transmitterPort,
|
|
||||||
SignalReceiverComponent receiver, string receiverPort)
|
|
||||||
{
|
|
||||||
if (_linkCollection.LinkExists(transmitter, transmitterPort, receiver, receiverPort))
|
|
||||||
{
|
{
|
||||||
if (_linkCollection.RemoveLink(transmitter, transmitterPort, receiver, receiverPort))
|
TryUpdateUI(linker, transmitter, receiver, bui);
|
||||||
{
|
args.Handled = true;
|
||||||
RaiseLocalEvent(receiver.Owner, new PortDisconnectedEvent(receiverPort));
|
return;
|
||||||
RaiseLocalEvent(transmitter.Owner, new PortDisconnectedEvent(transmitterPort));
|
|
||||||
entity.PopupMessageCursor(Loc.GetString("signal-linker-component-unlinked-port",
|
|
||||||
("port", receiverPort), ("machine", receiver)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var tport = transmitter.Outputs.GetPort(transmitterPort);
|
|
||||||
var rport = receiver.Inputs.GetPort(receiverPort);
|
|
||||||
|
|
||||||
if (!IsInRange(transmitter, receiver))
|
|
||||||
{
|
|
||||||
entity.PopupMessageCursor(Loc.GetString("signal-linker-component-out-of-range"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tport.MaxConnections != 0 && tport.MaxConnections >= _linkCollection.LinkCount(transmitter))
|
|
||||||
{
|
|
||||||
entity.PopupMessageCursor(Loc.GetString("signal-linker-component-max-connections-transmitter"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rport.MaxConnections != 0 && rport.MaxConnections <= _linkCollection.LinkCount(receiver))
|
|
||||||
{
|
|
||||||
entity.PopupMessageCursor(Loc.GetString("signal-linker-component-max-connections-receiver"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tport.Type != rport.Type)
|
|
||||||
{
|
|
||||||
entity.PopupMessageCursor(Loc.GetString("signal-linker-component-type-mismatch"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var linkAttempt = new LinkAttemptEvent(entity, transmitter, transmitterPort, receiver, receiverPort);
|
|
||||||
RaiseLocalEvent(receiver.Owner, linkAttempt);
|
|
||||||
RaiseLocalEvent(transmitter.Owner, linkAttempt);
|
|
||||||
|
|
||||||
if (linkAttempt.Cancelled) return;
|
|
||||||
|
|
||||||
var link = _linkCollection.AddLink(transmitter, transmitterPort, receiver, receiverPort);
|
|
||||||
if (link.Transmitterport.Signal != null)
|
|
||||||
RaiseLocalEvent(receiver.Owner,
|
|
||||||
new SignalReceivedEvent(receiverPort, link.Transmitterport.Signal));
|
|
||||||
|
|
||||||
entity.PopupMessageCursor(Loc.GetString("signal-linker-component-linked-port", ("port", receiverPort),
|
|
||||||
("machine", receiver.Owner)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void LinkerSaveInteraction(EntityUid entity, SignalLinkerComponent linkerComponent,
|
private bool TryGetOrOpenUI(ActorComponent actor, SignalLinkerComponent linker, [NotNullWhen(true)] out BoundUserInterface? bui)
|
||||||
SignalTransmitterComponent transmitterComponent, string transmitterPort)
|
|
||||||
{
|
{
|
||||||
if (SavePortInSignalLinker(linkerComponent, transmitterComponent, transmitterPort))
|
if (_userInterfaceSystem.TryGetUi(linker.Owner, SignalLinkerUiKey.Key, out bui))
|
||||||
{
|
{
|
||||||
entity.PopupMessageCursor(Loc.GetString("signal-linker-component-saved-port", ("port", transmitterPort),
|
bui.Open(actor.PlayerSession);
|
||||||
("machine", transmitterComponent.Owner)));
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool SavePortInSignalLinker(SignalLinkerComponent linker, SignalTransmitterComponent transmitter,
|
private bool TryUpdateUI(SignalLinkerComponent linker, SignalTransmitterComponent transmitter, SignalReceiverComponent receiver, BoundUserInterface? bui = null)
|
||||||
string port)
|
|
||||||
{
|
{
|
||||||
if (!transmitter.Outputs.ContainsPort(port)) return false;
|
if (bui == null && !_userInterfaceSystem.TryGetUi(linker.Owner, SignalLinkerUiKey.Key, out bui))
|
||||||
linker.Port = (transmitter, port);
|
return false;
|
||||||
|
|
||||||
|
var outKeys = transmitter.Outputs.Keys.ToList();
|
||||||
|
var inKeys = receiver.Inputs.Keys.ToList();
|
||||||
|
List<(int, int)> links = new();
|
||||||
|
for (int i = 0; i < outKeys.Count; i++)
|
||||||
|
foreach (var re in transmitter.Outputs[outKeys[i]])
|
||||||
|
if (re.Uid == receiver.Owner)
|
||||||
|
links.Add((i, inKeys.IndexOf(re.Port)));
|
||||||
|
|
||||||
|
bui.SetState(new SignalPortsState($"{Name(transmitter.Owner)} ({transmitter.Owner})", outKeys,
|
||||||
|
$"{Name(receiver.Owner)} ({receiver.Owner})", inKeys, links));
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool TryLink(SignalTransmitterComponent transmitter, SignalReceiverComponent receiver, SignalPortSelected args, EntityUid? popupUid = null)
|
||||||
|
{
|
||||||
|
if (!transmitter.Outputs.TryGetValue(args.TransmitterPort, out var receivers) ||
|
||||||
|
!receiver.Inputs.TryGetValue(args.ReceiverPort, out var transmitters))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!IsInRange(transmitter, receiver))
|
||||||
|
{
|
||||||
|
if (popupUid.HasValue)
|
||||||
|
_popupSystem.PopupCursor(Loc.GetString("signal-linker-component-out-of-range"),
|
||||||
|
Filter.Entities(popupUid.Value));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// allow other systems to refuse the connection
|
||||||
|
var linkAttempt = new LinkAttemptEvent(transmitter, args.TransmitterPort, receiver, args.ReceiverPort);
|
||||||
|
RaiseLocalEvent(transmitter.Owner, linkAttempt);
|
||||||
|
if (linkAttempt.Cancelled)
|
||||||
|
{
|
||||||
|
if (popupUid.HasValue)
|
||||||
|
_popupSystem.PopupCursor(Loc.GetString("signal-linker-component-connection-refused", ("machine", transmitter.Owner)),
|
||||||
|
Filter.Entities(popupUid.Value));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
RaiseLocalEvent(receiver.Owner, linkAttempt);
|
||||||
|
if (linkAttempt.Cancelled)
|
||||||
|
{
|
||||||
|
if (popupUid.HasValue)
|
||||||
|
_popupSystem.PopupCursor(Loc.GetString("signal-linker-component-connection-refused", ("machine", receiver.Owner)),
|
||||||
|
Filter.Entities(popupUid.Value));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
receivers.Add(new(receiver.Owner, args.ReceiverPort));
|
||||||
|
transmitters.Add(new(transmitter.Owner, args.TransmitterPort));
|
||||||
|
if (popupUid.HasValue)
|
||||||
|
_popupSystem.PopupCursor(Loc.GetString("signal-linker-component-linked-port",
|
||||||
|
("machine1", transmitter.Owner), ("port1", args.TransmitterPort),
|
||||||
|
("machine2", receiver.Owner), ("port2", args.ReceiverPort)),
|
||||||
|
Filter.Entities(popupUid.Value));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool IsInRange(SignalTransmitterComponent transmitterComponent,
|
private void OnSignalPortSelected(EntityUid uid, SignalLinkerComponent linker, SignalPortSelected args)
|
||||||
SignalReceiverComponent receiverComponent)
|
|
||||||
{
|
{
|
||||||
if (EntityManager.TryGetComponent<ApcPowerReceiverComponent?>(transmitterComponent.Owner, out var transmitterPowerReceiverComponent) &&
|
if (!TryComp(linker.savedTransmitter, out SignalTransmitterComponent? transmitter) ||
|
||||||
EntityManager.TryGetComponent<ApcPowerReceiverComponent?>(receiverComponent.Owner, out var receiverPowerReceiverComponent)
|
!TryComp(linker.savedReceiver, out SignalReceiverComponent? receiver) ||
|
||||||
) //&& todo are they on the same powernet?
|
!transmitter.Outputs.TryGetValue(args.TransmitterPort, out var receivers) ||
|
||||||
|
!receiver.Inputs.TryGetValue(args.ReceiverPort, out var transmitters))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (args.Session.AttachedEntity is not EntityUid attached || attached == default ||
|
||||||
|
!TryComp(attached, out ActorComponent? actor))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (receivers.Contains(new(receiver.Owner, args.ReceiverPort)) ||
|
||||||
|
transmitters.Contains(new(transmitter.Owner, args.TransmitterPort)))
|
||||||
|
{ // link already exists, remove it
|
||||||
|
if (receivers.Remove(new(receiver.Owner, args.ReceiverPort)) &&
|
||||||
|
transmitters.Remove(new(transmitter.Owner, args.TransmitterPort)))
|
||||||
|
{
|
||||||
|
RaiseLocalEvent(receiver.Owner, new PortDisconnectedEvent(args.ReceiverPort));
|
||||||
|
RaiseLocalEvent(transmitter.Owner, new PortDisconnectedEvent(args.TransmitterPort));
|
||||||
|
_popupSystem.PopupCursor(Loc.GetString("signal-linker-component-unlinked-port",
|
||||||
|
("machine1", transmitter.Owner), ("port1", args.TransmitterPort),
|
||||||
|
("machine2", receiver.Owner), ("port2", args.ReceiverPort)),
|
||||||
|
Filter.Entities(attached));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // something weird happened
|
||||||
|
// TODO log error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
return true;
|
TryLink(transmitter, receiver, args, attached);
|
||||||
}
|
}
|
||||||
|
|
||||||
return EntityManager.GetComponent<TransformComponent>(transmitterComponent.Owner).MapPosition.InRange(
|
TryUpdateUI(linker, transmitter, receiver);
|
||||||
EntityManager.GetComponent<TransformComponent>(receiverComponent.Owner).MapPosition, 30f);
|
}
|
||||||
|
|
||||||
|
private void OnLinkerClearSelected(EntityUid uid, SignalLinkerComponent linker, LinkerClearSelected args)
|
||||||
|
{
|
||||||
|
if (!TryComp(linker.savedTransmitter, out SignalTransmitterComponent? transmitter) ||
|
||||||
|
!TryComp(linker.savedReceiver, out SignalReceiverComponent? receiver))
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var (port, receivers) in transmitter.Outputs)
|
||||||
|
if (receivers.RemoveAll(id => id.Uid == receiver.Owner) > 0)
|
||||||
|
RaiseLocalEvent(transmitter.Owner, new PortDisconnectedEvent(port));
|
||||||
|
|
||||||
|
foreach (var (port, transmitters) in receiver.Inputs)
|
||||||
|
if (transmitters.RemoveAll(id => id.Uid == transmitter.Owner) > 0)
|
||||||
|
RaiseLocalEvent(receiver.Owner, new PortDisconnectedEvent(port));
|
||||||
|
|
||||||
|
TryUpdateUI(linker, transmitter, receiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLinkerLinkDefaultSelected(EntityUid uid, SignalLinkerComponent linker, LinkerLinkDefaultSelected args)
|
||||||
|
{
|
||||||
|
if (!TryComp(linker.savedTransmitter, out SignalTransmitterComponent? transmitter) ||
|
||||||
|
!TryComp(linker.savedReceiver, out SignalReceiverComponent? receiver) ||
|
||||||
|
args.Session.AttachedEntity is not EntityUid attached || attached == default ||
|
||||||
|
!TryComp(attached, out ActorComponent? actor))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (_defaultMappings.TryFirstOrDefault(map => !map.ExceptBy(transmitter.Outputs.Keys, item => item.Item1).Any() &&
|
||||||
|
!map.ExceptBy(receiver.Inputs.Keys, item => item.Item2).Any(), out var mapping))
|
||||||
|
{
|
||||||
|
foreach (var (port, receivers) in transmitter.Outputs)
|
||||||
|
if (receivers.RemoveAll(id => id.Uid == receiver.Owner) > 0)
|
||||||
|
RaiseLocalEvent(transmitter.Owner, new PortDisconnectedEvent(port));
|
||||||
|
|
||||||
|
foreach (var (port, transmitters) in receiver.Inputs)
|
||||||
|
if (transmitters.RemoveAll(id => id.Uid == transmitter.Owner) > 0)
|
||||||
|
RaiseLocalEvent(receiver.Owner, new PortDisconnectedEvent(port));
|
||||||
|
|
||||||
|
foreach (var (t, r) in mapping)
|
||||||
|
TryLink(transmitter, receiver, new(t, r));
|
||||||
|
}
|
||||||
|
|
||||||
|
TryUpdateUI(linker, transmitter, receiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnLinkerUIClosed(EntityUid uid, SignalLinkerComponent component, BoundUIClosedEvent args)
|
||||||
|
{
|
||||||
|
component.savedTransmitter = null;
|
||||||
|
component.savedReceiver = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private bool IsInRange(SignalTransmitterComponent transmitterComponent, SignalReceiverComponent receiverComponent)
|
||||||
|
{
|
||||||
|
if (TryComp(transmitterComponent.Owner, out ApcPowerReceiverComponent? transmitterPower) &&
|
||||||
|
TryComp(receiverComponent.Owner, out ApcPowerReceiverComponent? receiverPower) &&
|
||||||
|
transmitterPower.Provider?.Net == receiverPower.Provider?.Net)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return Comp<TransformComponent>(transmitterComponent.Owner).MapPosition.InRange(
|
||||||
|
Comp<TransformComponent>(receiverComponent.Owner).MapPosition, transmitterComponent.TransmissionRange);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,25 +10,23 @@ namespace Content.Server.MachineLinking.System
|
|||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<SignalSwitchComponent, ComponentInit>(OnInit);
|
||||||
SubscribeLocalEvent<SignalSwitchComponent, InteractHandEvent>(OnInteracted);
|
SubscribeLocalEvent<SignalSwitchComponent, InteractHandEvent>(OnInteracted);
|
||||||
SubscribeLocalEvent<SignalSwitchComponent, SignalValueRequestedEvent>(OnSignalValueRequested);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSignalValueRequested(EntityUid uid, SignalSwitchComponent component, SignalValueRequestedEvent args)
|
private void OnInit(EntityUid uid, SignalSwitchComponent component, ComponentInit args)
|
||||||
{
|
{
|
||||||
if (args.Port == "state")
|
var transmitter = EnsureComp<SignalTransmitterComponent>(uid);
|
||||||
{
|
foreach (string port in new[] { "On", "Off" })
|
||||||
args.Handled = true;
|
if (!transmitter.Outputs.ContainsKey(port))
|
||||||
args.Signal = component.State;
|
transmitter.AddPort(port);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInteracted(EntityUid uid, SignalSwitchComponent component, InteractHandEvent args)
|
private void OnInteracted(EntityUid uid, SignalSwitchComponent component, InteractHandEvent args)
|
||||||
{
|
{
|
||||||
component.State = !component.State;
|
component.State = !component.State;
|
||||||
RaiseLocalEvent(uid, new InvokePortEvent("state", component.State), false);
|
RaiseLocalEvent(uid, new InvokePortEvent(component.State ? "On" : "Off"), false);
|
||||||
RaiseLocalEvent(uid, new InvokePortEvent("stateChange"), false);
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ using Content.Server.MachineLinking.Events;
|
|||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.MachineLinking;
|
using Content.Shared.MachineLinking;
|
||||||
using Robust.Shared.GameObjects;
|
using Robust.Shared.GameObjects;
|
||||||
using Robust.Shared.IoC;
|
|
||||||
|
|
||||||
namespace Content.Server.MachineLinking.System
|
namespace Content.Server.MachineLinking.System
|
||||||
{
|
{
|
||||||
@@ -13,28 +12,29 @@ namespace Content.Server.MachineLinking.System
|
|||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<TwoWayLeverComponent, ComponentInit>(OnInit);
|
||||||
SubscribeLocalEvent<TwoWayLeverComponent, InteractHandEvent>(OnInteractHand);
|
SubscribeLocalEvent<TwoWayLeverComponent, InteractHandEvent>(OnInteractHand);
|
||||||
SubscribeLocalEvent<TwoWayLeverComponent, SignalValueRequestedEvent>(OnSignalValueRequested);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnSignalValueRequested(EntityUid uid, TwoWayLeverComponent component, SignalValueRequestedEvent args)
|
private void OnInit(EntityUid uid, TwoWayLeverComponent component, ComponentInit args)
|
||||||
{
|
{
|
||||||
args.Signal = component.State;
|
var transmitter = EnsureComp<SignalTransmitterComponent>(uid);
|
||||||
args.Handled = true;
|
foreach (string state in Enum.GetNames<TwoWayLeverState>())
|
||||||
|
if (!transmitter.Outputs.ContainsKey(state))
|
||||||
|
transmitter.AddPort(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnInteractHand(EntityUid uid, TwoWayLeverComponent component, InteractHandEvent args)
|
private void OnInteractHand(EntityUid uid, TwoWayLeverComponent component, InteractHandEvent args)
|
||||||
{
|
{
|
||||||
component.State = component.State switch
|
component.State = component.State switch
|
||||||
{
|
{
|
||||||
TwoWayLeverSignal.Middle => component.NextSignalLeft ? TwoWayLeverSignal.Left : TwoWayLeverSignal.Right,
|
TwoWayLeverState.Middle => component.NextSignalLeft ? TwoWayLeverState.Left : TwoWayLeverState.Right,
|
||||||
TwoWayLeverSignal.Right => TwoWayLeverSignal.Middle,
|
TwoWayLeverState.Right => TwoWayLeverState.Middle,
|
||||||
TwoWayLeverSignal.Left => TwoWayLeverSignal.Middle,
|
TwoWayLeverState.Left => TwoWayLeverState.Middle,
|
||||||
_ => throw new ArgumentOutOfRangeException()
|
_ => throw new ArgumentOutOfRangeException()
|
||||||
};
|
};
|
||||||
|
|
||||||
if (component.State == TwoWayLeverSignal.Middle)
|
if (component.State == TwoWayLeverState.Middle)
|
||||||
{
|
{
|
||||||
component.NextSignalLeft = !component.NextSignalLeft;
|
component.NextSignalLeft = !component.NextSignalLeft;
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ namespace Content.Server.MachineLinking.System
|
|||||||
appearanceComponent.SetData(TwoWayLeverVisuals.State, component.State);
|
appearanceComponent.SetData(TwoWayLeverVisuals.State, component.State);
|
||||||
}
|
}
|
||||||
|
|
||||||
RaiseLocalEvent(uid, new InvokePortEvent("state", component.State));
|
RaiseLocalEvent(uid, new InvokePortEvent(component.State.ToString()));
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ namespace Content.Server.Physics.Controllers
|
|||||||
|
|
||||||
conveyorRot += comp.Angle;
|
conveyorRot += comp.Angle;
|
||||||
|
|
||||||
if (comp.State == ConveyorState.Reversed)
|
if (comp.State == ConveyorState.Reverse)
|
||||||
{
|
{
|
||||||
conveyorRot += MathF.PI;
|
conveyorRot += MathF.PI;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,6 @@ namespace Content.Shared.Conveyor
|
|||||||
{
|
{
|
||||||
Off,
|
Off,
|
||||||
Forward,
|
Forward,
|
||||||
Reversed
|
Reverse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace Content.Shared.MachineLinking
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public enum TwoWayLeverSignal : byte
|
public enum TwoWayLeverState : byte
|
||||||
{
|
{
|
||||||
Middle,
|
Middle,
|
||||||
Right,
|
Right,
|
||||||
|
|||||||
@@ -4,13 +4,7 @@ using Robust.Shared.Serialization;
|
|||||||
namespace Content.Shared.MachineLinking
|
namespace Content.Shared.MachineLinking
|
||||||
{
|
{
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public enum SignalTransmitterUiKey
|
public enum SignalLinkerUiKey
|
||||||
{
|
|
||||||
Key
|
|
||||||
}
|
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
|
||||||
public enum SignalReceiverUiKey
|
|
||||||
{
|
{
|
||||||
Key
|
Key
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,29 +9,46 @@ namespace Content.Shared.MachineLinking
|
|||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public sealed class SignalPortsState : BoundUserInterfaceState
|
public sealed class SignalPortsState : BoundUserInterfaceState
|
||||||
{
|
{
|
||||||
|
public readonly string TransmitterName;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A Dictionary containing all ports and wether or not they can be selected.
|
/// A List of all ports on the selected transmitter
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly Dictionary<string, bool> Ports;
|
public readonly List<string> TransmitterPorts;
|
||||||
|
|
||||||
public SignalPortsState(string[] ports) : this(ports.ToDictionary(s => s, _ => true))
|
public readonly string ReceiverName;
|
||||||
{
|
/// <summary>
|
||||||
}
|
/// A List of all ports on the selected receiver
|
||||||
|
/// </summary>
|
||||||
|
public readonly List<string> ReceiverPorts;
|
||||||
|
|
||||||
public SignalPortsState(Dictionary<string, bool> ports)
|
public readonly List<(int, int)> Links;
|
||||||
|
|
||||||
|
public SignalPortsState(string transmitterName, List<string> transmitterPorts, string receiverName, List<string> receiverPorts, List<(int, int)> links)
|
||||||
{
|
{
|
||||||
Ports = ports;
|
TransmitterName = transmitterName;
|
||||||
|
TransmitterPorts = transmitterPorts;
|
||||||
|
ReceiverName = receiverName;
|
||||||
|
ReceiverPorts = receiverPorts;
|
||||||
|
Links = links;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Serializable, NetSerializable]
|
[Serializable, NetSerializable]
|
||||||
public sealed class SignalPortSelected : BoundUserInterfaceMessage
|
public sealed class SignalPortSelected : BoundUserInterfaceMessage
|
||||||
{
|
{
|
||||||
public readonly string Port;
|
public readonly string TransmitterPort;
|
||||||
|
public readonly string ReceiverPort;
|
||||||
|
|
||||||
public SignalPortSelected(string port)
|
public SignalPortSelected(string transmitterPort, string receiverPort)
|
||||||
{
|
{
|
||||||
Port = port;
|
TransmitterPort = transmitterPort;
|
||||||
|
ReceiverPort = receiverPort;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class LinkerClearSelected : BoundUserInterfaceMessage { }
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public sealed class LinkerLinkDefaultSelected : BoundUserInterfaceMessage { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
signal-linker-component-saved-port = Successfully saved port '{$port}' of {$machine}!
|
signal-linker-component-saved = Successfully saved link to {$machine}!
|
||||||
signal-linker-component-linked-port = Successfully linked saved port to port '{$port}' of {$machine}!
|
signal-linker-component-linked-port = Successfully linked {$machine1}:{$port1} to {$machine2}:{$port2}!
|
||||||
signal-linker-component-unlinked-port = Successfully unlinked saved port from port '{$port}' of {$machine}!
|
signal-linker-component-unlinked-port = Successfully unlinked {$machine1}:{$port1} from {$machine2}:{$port2}!
|
||||||
|
signal-linker-component-connection-refused = {$machine} refused the connection!
|
||||||
signal-linker-component-max-connections-receiver = Maximum connections reached on the receiver!
|
signal-linker-component-max-connections-receiver = Maximum connections reached on the receiver!
|
||||||
signal-linker-component-max-connections-transmitter = Maximum connections reached on the transmitter!
|
signal-linker-component-max-connections-transmitter = Maximum connections reached on the transmitter!
|
||||||
|
|
||||||
|
|||||||
@@ -181,6 +181,10 @@
|
|||||||
qualities:
|
qualities:
|
||||||
- Pulsing
|
- Pulsing
|
||||||
- type: SignalLinker
|
- type: SignalLinker
|
||||||
|
- type: UserInterface
|
||||||
|
interfaces:
|
||||||
|
- key: enum.SignalLinkerUiKey.Key
|
||||||
|
type: SignalPortSelectorBoundUserInterface
|
||||||
- type: Tag
|
- type: Tag
|
||||||
tags:
|
tags:
|
||||||
- DroneUsable
|
- DroneUsable
|
||||||
|
|||||||
@@ -66,11 +66,7 @@
|
|||||||
- type: IconSmooth
|
- type: IconSmooth
|
||||||
key: walls
|
key: walls
|
||||||
mode: NoSprite
|
mode: NoSprite
|
||||||
- type: SignalReceiver
|
- type: DoorSignalControl
|
||||||
inputs:
|
|
||||||
- name: pressed
|
|
||||||
- type: ToggleDoorOnTrigger
|
|
||||||
- type: TriggerOnSignalReceived
|
|
||||||
placement:
|
placement:
|
||||||
mode: SnapgridCenter
|
mode: SnapgridCenter
|
||||||
|
|
||||||
|
|||||||
@@ -49,8 +49,3 @@
|
|||||||
state_off: grinder-o0
|
state_off: grinder-o0
|
||||||
- type: Recycler
|
- type: Recycler
|
||||||
- type: Conveyor
|
- type: Conveyor
|
||||||
- type: SignalReceiver
|
|
||||||
inputs:
|
|
||||||
- name: state
|
|
||||||
type: Content.Shared.MachineLinking.TwoWayLeverSignal
|
|
||||||
maxConnections: 1
|
|
||||||
|
|||||||
@@ -32,14 +32,6 @@
|
|||||||
energy: 0.8
|
energy: 0.8
|
||||||
softness: 1
|
softness: 1
|
||||||
offset: "0, -0.5"
|
offset: "0, -0.5"
|
||||||
- type: SignalReceiver
|
|
||||||
inputs:
|
|
||||||
- name: state
|
|
||||||
type: bool
|
|
||||||
- type: UserInterface
|
|
||||||
interfaces:
|
|
||||||
- key: enum.SignalReceiverUiKey.Key
|
|
||||||
type: SignalPortSelectorBoundUserInterface
|
|
||||||
- type: Damageable
|
- type: Damageable
|
||||||
damageContainer: Inorganic
|
damageContainer: Inorganic
|
||||||
damageModifierSet: Metallic
|
damageModifierSet: Metallic
|
||||||
|
|||||||
@@ -13,15 +13,6 @@
|
|||||||
state: on
|
state: on
|
||||||
- type: SignalSwitch
|
- type: SignalSwitch
|
||||||
- type: Rotatable
|
- type: Rotatable
|
||||||
- type: SignalTransmitter
|
|
||||||
outputs:
|
|
||||||
- name: state
|
|
||||||
type: bool
|
|
||||||
- name: stateChange
|
|
||||||
- type: UserInterface
|
|
||||||
interfaces:
|
|
||||||
- key: enum.SignalTransmitterUiKey.Key
|
|
||||||
type: SignalPortSelectorBoundUserInterface
|
|
||||||
placement:
|
placement:
|
||||||
mode: SnapgridCenter
|
mode: SnapgridCenter
|
||||||
snap:
|
snap:
|
||||||
@@ -42,9 +33,6 @@
|
|||||||
state: dead
|
state: dead
|
||||||
- type: SignalButton
|
- type: SignalButton
|
||||||
- type: Rotatable
|
- type: Rotatable
|
||||||
- type: SignalTransmitter
|
|
||||||
outputs:
|
|
||||||
- name: pressed
|
|
||||||
placement:
|
placement:
|
||||||
mode: SnapgridCenter
|
mode: SnapgridCenter
|
||||||
snap:
|
snap:
|
||||||
@@ -78,3 +66,36 @@
|
|||||||
mode: SnapgridCenter
|
mode: SnapgridCenter
|
||||||
snap:
|
snap:
|
||||||
- Wallmount
|
- Wallmount
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: TwoWayLever
|
||||||
|
name: two way lever
|
||||||
|
description: A two way lever.
|
||||||
|
placement:
|
||||||
|
mode: SnapgridCenter
|
||||||
|
components:
|
||||||
|
- type: Clickable
|
||||||
|
- type: InteractionOutline
|
||||||
|
- type: Sprite
|
||||||
|
netsync: false
|
||||||
|
sprite: Structures/conveyor.rsi
|
||||||
|
state: switch-off
|
||||||
|
- type: TwoWayLever
|
||||||
|
- type: Appearance
|
||||||
|
visuals:
|
||||||
|
- type: TwoWayLeverVisualizer
|
||||||
|
state_forward: switch-fwd
|
||||||
|
state_off: switch-off
|
||||||
|
state_reversed: switch-rev
|
||||||
|
- type: Construction
|
||||||
|
graph: LeverGraph
|
||||||
|
node: lever
|
||||||
|
- type: Destructible
|
||||||
|
thresholds:
|
||||||
|
- trigger:
|
||||||
|
!type:DamageTrigger
|
||||||
|
damage: 100
|
||||||
|
behaviors:
|
||||||
|
- !type:DoActsBehavior
|
||||||
|
acts: [ "Destruction" ]
|
||||||
|
|
||||||
|
|||||||
@@ -16,11 +16,6 @@
|
|||||||
sprite: Structures/conveyor.rsi
|
sprite: Structures/conveyor.rsi
|
||||||
state: conveyor_started_cw
|
state: conveyor_started_cw
|
||||||
drawdepth: FloorObjects
|
drawdepth: FloorObjects
|
||||||
- type: SignalReceiver
|
|
||||||
inputs:
|
|
||||||
- name: state
|
|
||||||
type: Content.Shared.MachineLinking.TwoWayLeverSignal
|
|
||||||
maxConnections: 1
|
|
||||||
- type: ApcPowerReceiver
|
- type: ApcPowerReceiver
|
||||||
- type: ExtensionCableReceiver
|
- type: ExtensionCableReceiver
|
||||||
- type: Conveyor
|
- type: Conveyor
|
||||||
@@ -61,38 +56,3 @@
|
|||||||
graph: ConveyorGraph
|
graph: ConveyorGraph
|
||||||
node: item
|
node: item
|
||||||
|
|
||||||
- type: entity
|
|
||||||
id: TwoWayLever
|
|
||||||
name: two way lever
|
|
||||||
description: A two way lever.
|
|
||||||
placement:
|
|
||||||
mode: SnapgridCenter
|
|
||||||
components:
|
|
||||||
- type: Clickable
|
|
||||||
- type: InteractionOutline
|
|
||||||
- type: Sprite
|
|
||||||
netsync: false
|
|
||||||
sprite: Structures/conveyor.rsi
|
|
||||||
state: switch-off
|
|
||||||
- type: TwoWayLever
|
|
||||||
- type: SignalTransmitter
|
|
||||||
outputs:
|
|
||||||
- name: state
|
|
||||||
type: Content.Shared.MachineLinking.TwoWayLeverSignal
|
|
||||||
- type: Appearance
|
|
||||||
visuals:
|
|
||||||
- type: TwoWayLeverVisualizer
|
|
||||||
state_forward: switch-fwd
|
|
||||||
state_off: switch-off
|
|
||||||
state_reversed: switch-rev
|
|
||||||
- type: Construction
|
|
||||||
graph: LeverGraph
|
|
||||||
node: lever
|
|
||||||
- type: Destructible
|
|
||||||
thresholds:
|
|
||||||
- trigger:
|
|
||||||
!type:DamageTrigger
|
|
||||||
damage: 100
|
|
||||||
behaviors:
|
|
||||||
- !type:DoActsBehavior
|
|
||||||
acts: [ "Destruction" ]
|
|
||||||
@@ -33,14 +33,6 @@
|
|||||||
- !type:PlaySoundBehavior
|
- !type:PlaySoundBehavior
|
||||||
sound:
|
sound:
|
||||||
path: /Audio/Effects/metalbreak.ogg
|
path: /Audio/Effects/metalbreak.ogg
|
||||||
- type: SignalReceiver
|
|
||||||
inputs:
|
|
||||||
- name: state
|
|
||||||
type: bool
|
|
||||||
- type: UserInterface
|
|
||||||
interfaces:
|
|
||||||
- key: enum.SignalReceiverUiKey.Key
|
|
||||||
type: SignalPortSelectorBoundUserInterface
|
|
||||||
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
|
|||||||
Reference in New Issue
Block a user