machine linking refactor to ecs (#4323)
* started work * some more work, ui working (somewhat) * stuff * reorganization * some more reorg * conveyors * conveyors working * finalized (dis)connection added linkattempt added feedback text work on conveyors * removed command add rangecheck * fixed inrange check * handling * ui no longer kanser, ship it * adresses reviews * reformats file * reformats file Co-authored-by: Paul <ritter.paul1+git@googlemail.com>
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
using Content.Shared.MachineLinking;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Client.MachineLinking.UI
|
||||
{
|
||||
public class SignalPortSelectorBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
private SignalPortSelectorMenu? _menu;
|
||||
|
||||
public SignalPortSelectorBoundUserInterface([NotNull] ClientUserInterfaceComponent owner, [NotNull] object uiKey) : base(owner, uiKey)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
_menu = new SignalPortSelectorMenu(this);
|
||||
_menu.OnClose += Close;
|
||||
_menu.OpenCentered();
|
||||
}
|
||||
|
||||
protected override void UpdateState(BoundUserInterfaceState state)
|
||||
{
|
||||
base.UpdateState(state);
|
||||
switch (state)
|
||||
{
|
||||
case SignalPortsState data:
|
||||
_menu?.UpdateState(data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void OnPortSelected(string port)
|
||||
{
|
||||
SendMessage(new SignalPortSelected(port));
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
if (!disposing)
|
||||
return;
|
||||
|
||||
_menu?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<customControls:SS14Window xmlns:customControls="https://spacestation14.io"
|
||||
Title="Port Selector" MinSize="200 200">
|
||||
<customControls:ItemList Name="ButtonContainer" VerticalExpand="True" HorizontalExpand="True" SelectMode="Button"/>
|
||||
</customControls:SS14Window>
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.MachineLinking;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client.MachineLinking.UI
|
||||
{
|
||||
[GenerateTypedNameReferences]
|
||||
public partial class SignalPortSelectorMenu : SS14Window
|
||||
{
|
||||
private SignalPortSelectorBoundUserInterface _bui;
|
||||
|
||||
public SignalPortSelectorMenu(SignalPortSelectorBoundUserInterface boundUserInterface)
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
_bui = boundUserInterface;
|
||||
}
|
||||
|
||||
public void UpdateState(SignalPortsState state)
|
||||
{
|
||||
ButtonContainer.Clear();
|
||||
foreach (var port in state.Ports)
|
||||
{
|
||||
var portBtn = new ItemList.Item(ButtonContainer)
|
||||
{
|
||||
Text = port.Key,
|
||||
Disabled = !port.Value
|
||||
};
|
||||
portBtn.OnSelected += _ => _bui.OnPortSelected(port.Key);
|
||||
ButtonContainer.Add(portBtn);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -14,7 +14,7 @@ using Robust.Shared.ViewVariables;
|
||||
namespace Content.Server.Conveyor
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class ConveyorComponent : Component, ISignalReceiver<TwoWayLeverSignal>, ISignalReceiver<bool>
|
||||
public class ConveyorComponent : Component
|
||||
{
|
||||
public override string Name => "Conveyor";
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace Content.Server.Conveyor
|
||||
return true;
|
||||
}
|
||||
|
||||
public void TriggerSignal(TwoWayLeverSignal signal)
|
||||
public void SetState(TwoWayLeverSignal signal)
|
||||
{
|
||||
State = signal switch
|
||||
{
|
||||
@@ -160,10 +160,5 @@ namespace Content.Server.Conveyor
|
||||
_ => ConveyorState.Off
|
||||
};
|
||||
}
|
||||
|
||||
public void TriggerSignal(bool signal)
|
||||
{
|
||||
State = signal ? ConveyorState.Forward : ConveyorState.Off;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
51
Content.Server/Conveyor/ConveyorSystem.cs
Normal file
51
Content.Server/Conveyor/ConveyorSystem.cs
Normal file
@@ -0,0 +1,51 @@
|
||||
using Content.Server.MachineLinking.Events;
|
||||
using Content.Server.MachineLinking.Models;
|
||||
using Content.Server.Stunnable.Components;
|
||||
using Content.Shared.MachineLinking;
|
||||
using Content.Shared.Notification.Managers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Localization;
|
||||
|
||||
namespace Content.Server.Conveyor
|
||||
{
|
||||
public class ConveyorSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ConveyorComponent, SignalReceivedEvent>(OnSignalReceived);
|
||||
SubscribeLocalEvent<ConveyorComponent, PortDisconnectedEvent>(OnPortDisconnected);
|
||||
SubscribeLocalEvent<ConveyorComponent, LinkAttemptEvent>(OnLinkAttempt);
|
||||
}
|
||||
|
||||
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();
|
||||
if (args.Attemptee.TryGetComponent<StunnableComponent>(out var stunnableComponent))
|
||||
{
|
||||
stunnableComponent.Paralyze(2);
|
||||
component.Owner.PopupMessage(args.Attemptee, Loc.GetString("conveyor-component-failed-link"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnPortDisconnected(EntityUid uid, ConveyorComponent component, PortDisconnectedEvent args)
|
||||
{
|
||||
component.SetState(TwoWayLeverSignal.Middle);
|
||||
}
|
||||
|
||||
private void OnSignalReceived(EntityUid uid, ConveyorComponent component, SignalReceivedEvent args)
|
||||
{
|
||||
switch (args.Port)
|
||||
{
|
||||
case "state":
|
||||
component.SetState((TwoWayLeverSignal) args.Value!);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,6 @@ using System.Threading.Tasks;
|
||||
using Content.Server.Ghost;
|
||||
using Content.Server.Hands.Components;
|
||||
using Content.Server.Items;
|
||||
using Content.Server.MachineLinking.Components;
|
||||
using Content.Server.MachineLinking.Signals;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Temperature.Components;
|
||||
using Content.Shared.Actions.Behaviors;
|
||||
@@ -12,7 +10,6 @@ using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Components;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Light;
|
||||
using Content.Shared.Notification;
|
||||
using Content.Shared.Notification.Managers;
|
||||
using Content.Shared.Sound;
|
||||
using Robust.Server.GameObjects;
|
||||
@@ -33,7 +30,7 @@ namespace Content.Server.Light.Components
|
||||
/// Component that represents a wall light. It has a light bulb that can be replaced when broken.
|
||||
/// </summary>
|
||||
[RegisterComponent]
|
||||
public class PoweredLightComponent : Component, IInteractHand, IInteractUsing, IMapInit, ISignalReceiver<bool>, ISignalReceiver<ToggleSignal>, IGhostBooAffected
|
||||
public class PoweredLightComponent : Component, IInteractHand, IInteractUsing, IMapInit, IGhostBooAffected
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
|
||||
@@ -309,13 +306,7 @@ namespace Content.Server.Light.Components
|
||||
UpdateLight();
|
||||
}
|
||||
|
||||
public void TriggerSignal(bool signal)
|
||||
{
|
||||
_on = signal;
|
||||
UpdateLight();
|
||||
}
|
||||
|
||||
public void TriggerSignal(ToggleSignal signal)
|
||||
public void ToggleLight()
|
||||
{
|
||||
_on = !_on;
|
||||
UpdateLight();
|
||||
|
||||
26
Content.Server/Light/EntitySystems/PoweredLightSystem.cs
Normal file
26
Content.Server/Light/EntitySystems/PoweredLightSystem.cs
Normal file
@@ -0,0 +1,26 @@
|
||||
using Content.Server.Light.Components;
|
||||
using Content.Server.MachineLinking.Events;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.Light.EntitySystems
|
||||
{
|
||||
public class PoweredLightSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<PoweredLightComponent, SignalReceivedEvent>(OnSignalReceived);
|
||||
}
|
||||
|
||||
private void OnSignalReceived(EntityUid uid, PoweredLightComponent component, SignalReceivedEvent args)
|
||||
{
|
||||
switch (args.Port)
|
||||
{
|
||||
case "toggle":
|
||||
component.ToggleLight();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
namespace Content.Server.MachineLinking.Components
|
||||
{
|
||||
public interface ISignalReceiver<in T>
|
||||
{
|
||||
void TriggerSignal(T signal);
|
||||
}
|
||||
}
|
||||
@@ -1,45 +1,10 @@
|
||||
using Content.Server.MachineLinking.Signals;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Notification;
|
||||
using Content.Shared.Notification.Managers;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Localization;
|
||||
|
||||
namespace Content.Server.MachineLinking.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class SignalButtonComponent : Component, IActivate, IInteractHand
|
||||
public class SignalButtonComponent : Component
|
||||
{
|
||||
public override string Name => "SignalButton";
|
||||
|
||||
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||
{
|
||||
TransmitSignal(eventArgs.User);
|
||||
}
|
||||
|
||||
bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs)
|
||||
{
|
||||
TransmitSignal(eventArgs.User);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void TransmitSignal(IEntity user)
|
||||
{
|
||||
if (!Owner.TryGetComponent<SignalTransmitterComponent>(out var transmitter))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (transmitter.TransmitSignal(new ToggleSignal()))
|
||||
{
|
||||
// Since the button doesn't have an animation, I'm going to use a popup message
|
||||
Owner.PopupMessage(user, Loc.GetString("signal-button-component-transmit-signal-success-message"));
|
||||
}
|
||||
else
|
||||
{
|
||||
Owner.PopupMessage(user, Loc.GetString("signal-button-component-transmit-signal-no-receivers-message"));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,13 +9,6 @@ namespace Content.Server.MachineLinking.Components
|
||||
public override string Name => "SignalLinker";
|
||||
|
||||
[ViewVariables]
|
||||
public SignalTransmitterComponent? Link { get; set; }
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
Link = null;
|
||||
}
|
||||
public (SignalTransmitterComponent transmitter, string port)? Port;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,125 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Tools.Components;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Notification;
|
||||
using Content.Shared.Notification.Managers;
|
||||
using Content.Shared.Tool;
|
||||
using Content.Server.MachineLinking.Models;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.MachineLinking.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class SignalReceiverComponent : Component, IInteractUsing
|
||||
public class SignalReceiverComponent : Component
|
||||
{
|
||||
public override string Name => "SignalReceiver";
|
||||
|
||||
private readonly List<SignalTransmitterComponent> _transmitters = new();
|
||||
[DataField("inputs")]
|
||||
private List<SignalPort> _inputs = new();
|
||||
|
||||
[DataField("maxTransmitters")]
|
||||
private int? _maxTransmitters = default;
|
||||
|
||||
public void DistributeSignal<T>(T state)
|
||||
{
|
||||
foreach (var comp in Owner.GetAllComponents<ISignalReceiver<T>>())
|
||||
{
|
||||
comp.TriggerSignal(state);
|
||||
}
|
||||
}
|
||||
|
||||
public bool Subscribe(SignalTransmitterComponent transmitter)
|
||||
{
|
||||
if (_transmitters.Contains(transmitter))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_transmitters.Count >= _maxTransmitters) return false;
|
||||
|
||||
transmitter.Subscribe(this);
|
||||
_transmitters.Add(transmitter);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Unsubscribe(SignalTransmitterComponent transmitter)
|
||||
{
|
||||
transmitter.Unsubscribe(this);
|
||||
_transmitters.Remove(transmitter);
|
||||
}
|
||||
|
||||
public void UnsubscribeAll()
|
||||
{
|
||||
for (var i = _transmitters.Count-1; i >= 0; i--)
|
||||
{
|
||||
var transmitter = _transmitters[i];
|
||||
if (transmitter.Deleted)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
transmitter.Unsubscribe(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribes/Unsubscribes a transmitter to this component. Returns whether it was successful.
|
||||
/// </summary>
|
||||
/// <param name="user"></param>
|
||||
/// <param name="transmitter"></param>
|
||||
/// <returns></returns>
|
||||
public bool Interact(IEntity user, SignalTransmitterComponent? transmitter)
|
||||
{
|
||||
if (transmitter == null)
|
||||
{
|
||||
user.PopupMessage(Loc.GetString("signal-receiver-component-interact-no-transmitter-message"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (_transmitters.Contains(transmitter))
|
||||
{
|
||||
Unsubscribe(transmitter);
|
||||
Owner.PopupMessage(user, Loc.GetString("signal-receiver-component-interact-unlinked"));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (transmitter.Range > 0 && !Owner.Transform.Coordinates.InRange(Owner.EntityManager, transmitter.Owner.Transform.Coordinates, transmitter.Range))
|
||||
{
|
||||
Owner.PopupMessage(user, Loc.GetString("signal-receiver-component-interact-out-of-range"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Subscribe(transmitter))
|
||||
{
|
||||
Owner.PopupMessage(user, Loc.GetString("signal-receiver-component-interact-max-transmitters-limit"));
|
||||
return false;
|
||||
}
|
||||
Owner.PopupMessage(user, Loc.GetString("signal-receiver-component-interact-success"));
|
||||
return true;
|
||||
}
|
||||
|
||||
async Task<bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs)
|
||||
{
|
||||
if (!eventArgs.Using.TryGetComponent<ToolComponent>(out var tool))
|
||||
return false;
|
||||
|
||||
if (tool.HasQuality(ToolQuality.Multitool)
|
||||
&& eventArgs.Using.TryGetComponent<SignalLinkerComponent>(out var linker))
|
||||
{
|
||||
return Interact(eventArgs.User, linker.Link);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
|
||||
UnsubscribeAll();
|
||||
|
||||
_transmitters.Clear();
|
||||
}
|
||||
[ViewVariables]
|
||||
public IReadOnlyList<SignalPort> Inputs => _inputs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,86 +1,12 @@
|
||||
using Content.Shared.ActionBlocker;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.MachineLinking;
|
||||
using Content.Shared.Notification.Managers;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
|
||||
namespace Content.Server.MachineLinking.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class SignalSwitchComponent : Component, IInteractHand, IActivate
|
||||
public class SignalSwitchComponent : Component
|
||||
{
|
||||
public override string Name => "SignalSwitch";
|
||||
|
||||
[DataField("on")]
|
||||
private bool _on;
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
UpdateSprite();
|
||||
}
|
||||
|
||||
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||
{
|
||||
TransmitSignal(eventArgs.User);
|
||||
}
|
||||
|
||||
bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs)
|
||||
{
|
||||
TransmitSignal(eventArgs.User);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void TransmitSignal(IEntity user)
|
||||
{
|
||||
_on = !_on;
|
||||
|
||||
UpdateSprite();
|
||||
|
||||
if (!Owner.TryGetComponent<SignalTransmitterComponent>(out var transmitter))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!transmitter.TransmitSignal(_on))
|
||||
{
|
||||
Owner.PopupMessage(user, Loc.GetString("signal-switch-component-transmit-no-receivers-connected"));
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSprite()
|
||||
{
|
||||
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
|
||||
{
|
||||
appearance.SetData(SignalSwitchVisuals.On, _on);
|
||||
}
|
||||
}
|
||||
|
||||
[Verb]
|
||||
private sealed class ToggleSwitchVerb : Verb<SignalSwitchComponent>
|
||||
{
|
||||
protected override void Activate(IEntity user, SignalSwitchComponent component)
|
||||
{
|
||||
component.TransmitSignal(user);
|
||||
}
|
||||
|
||||
protected override void GetData(IEntity user, SignalSwitchComponent component, VerbData data)
|
||||
{
|
||||
if (!EntitySystem.Get<ActionBlockerSystem>().CanInteract(user))
|
||||
{
|
||||
data.Visibility = VerbVisibility.Invisible;
|
||||
return;
|
||||
}
|
||||
|
||||
data.Text = Loc.GetString("toggle-switch-verb-get-data-text");
|
||||
data.Visibility = VerbVisibility.Visible;
|
||||
}
|
||||
}
|
||||
public bool State;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,159 +1,21 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Tools.Components;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Notification;
|
||||
using Content.Shared.Notification.Managers;
|
||||
using Content.Shared.Tool;
|
||||
using Content.Server.MachineLinking.Models;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Server.MachineLinking.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class SignalTransmitterComponent : Component, IInteractUsing, ISerializationHooks
|
||||
public class SignalTransmitterComponent : Component
|
||||
{
|
||||
public override string Name => "SignalTransmitter";
|
||||
|
||||
private List<SignalReceiverComponent>? _unresolvedReceivers = new();
|
||||
private List<SignalReceiverComponent> _receivers = new();
|
||||
[DataField("outputs")]
|
||||
private List<SignalPort> _outputs = new();
|
||||
|
||||
/// <summary>
|
||||
/// 0 is unlimited range
|
||||
/// </summary>
|
||||
[ViewVariables]
|
||||
[DataField("range")]
|
||||
public float Range { get; private set; } = 10;
|
||||
|
||||
[DataField("signalReceivers")] private List<EntityUid> _receiverIds = new();
|
||||
|
||||
void ISerializationHooks.BeforeSerialization()
|
||||
{
|
||||
var entityList = new List<EntityUid>();
|
||||
|
||||
foreach (var receiver in _receivers)
|
||||
{
|
||||
if (receiver.Deleted)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
entityList.Add(receiver.Owner.Uid);
|
||||
}
|
||||
|
||||
_receiverIds = entityList;
|
||||
}
|
||||
|
||||
void ISerializationHooks.AfterDeserialization()
|
||||
{
|
||||
_unresolvedReceivers = new List<SignalReceiverComponent>();
|
||||
|
||||
foreach (var id in _receiverIds)
|
||||
{
|
||||
if (!Owner.EntityManager.TryGetEntity(id, out var entity) ||
|
||||
!entity.TryGetComponent<SignalReceiverComponent>(out var receiver))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_unresolvedReceivers.Add(receiver);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_receivers = new List<SignalReceiverComponent>();
|
||||
|
||||
if (_unresolvedReceivers != null)
|
||||
{
|
||||
foreach (var receiver in _unresolvedReceivers)
|
||||
{
|
||||
receiver.Subscribe(this);
|
||||
}
|
||||
|
||||
_unresolvedReceivers = null;
|
||||
}
|
||||
}
|
||||
|
||||
public bool TransmitSignal<T>(T signal)
|
||||
{
|
||||
if (_receivers.Count == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach (var receiver in _receivers)
|
||||
{
|
||||
if (Range > 0 && !Owner.Transform.Coordinates.InRange(Owner.EntityManager, receiver.Owner.Transform.Coordinates, Range))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
receiver.DistributeSignal(signal);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void Subscribe(SignalReceiverComponent receiver)
|
||||
{
|
||||
if (_receivers.Contains(receiver))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_receivers.Add(receiver);
|
||||
}
|
||||
|
||||
public void Unsubscribe(SignalReceiverComponent receiver)
|
||||
{
|
||||
_receivers.Remove(receiver);
|
||||
}
|
||||
|
||||
public SignalTransmitterComponent GetSignal(IEntity? user)
|
||||
{
|
||||
if (user != null)
|
||||
{
|
||||
Owner.PopupMessage(user, Loc.GetString("signal-transmitter-component-get-signal-success"));
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
async Task<bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs)
|
||||
{
|
||||
if (!eventArgs.Using.TryGetComponent<ToolComponent>(out var tool))
|
||||
return false;
|
||||
|
||||
if (tool.HasQuality(ToolQuality.Multitool)
|
||||
&& eventArgs.Using.TryGetComponent<SignalLinkerComponent>(out var linker))
|
||||
{
|
||||
linker.Link = GetSignal(eventArgs.User);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
protected override void Shutdown()
|
||||
{
|
||||
base.Shutdown();
|
||||
|
||||
for (var i = _receivers.Count-1; i >= 0; i++)
|
||||
{
|
||||
var receiver = _receivers[i];
|
||||
if (receiver.Deleted)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
receiver.Unsubscribe(this);
|
||||
}
|
||||
|
||||
_receivers.Clear();
|
||||
}
|
||||
public IReadOnlyList<SignalPort> Outputs => _outputs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.MachineLinking;
|
||||
using Content.Shared.Notification;
|
||||
using Content.Shared.Notification.Managers;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Localization;
|
||||
|
||||
namespace Content.Server.MachineLinking.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
[ComponentReference(typeof(IActivate))]
|
||||
public class SignalTwoWayLeverComponent : SignalTransmitterComponent, IInteractHand, IActivate
|
||||
{
|
||||
public override string Name => "TwoWayLever";
|
||||
|
||||
private TwoWayLeverSignal _state = TwoWayLeverSignal.Middle;
|
||||
|
||||
private bool _nextForward = true;
|
||||
|
||||
public TwoWayLeverSignal State
|
||||
{
|
||||
get => _state;
|
||||
private set
|
||||
{
|
||||
_state = value;
|
||||
|
||||
if (Owner.TryGetComponent(out AppearanceComponent? appearance))
|
||||
{
|
||||
appearance.SetData(TwoWayLeverVisuals.State, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void NextState(IEntity user)
|
||||
{
|
||||
State = State switch
|
||||
{
|
||||
TwoWayLeverSignal.Left => TwoWayLeverSignal.Middle,
|
||||
TwoWayLeverSignal.Middle => _nextForward ? TwoWayLeverSignal.Right : TwoWayLeverSignal.Left,
|
||||
TwoWayLeverSignal.Right => TwoWayLeverSignal.Middle,
|
||||
_ => TwoWayLeverSignal.Middle
|
||||
};
|
||||
|
||||
if (State == TwoWayLeverSignal.Left || State == TwoWayLeverSignal.Right) _nextForward = !_nextForward;
|
||||
|
||||
if (!TransmitSignal(State))
|
||||
{
|
||||
Owner.PopupMessage(user, Loc.GetString("signal-two-way-lever-component-next-state-no-receivers-connected"));
|
||||
}
|
||||
}
|
||||
|
||||
bool IInteractHand.InteractHand(InteractHandEventArgs eventArgs)
|
||||
{
|
||||
NextState(eventArgs.User);
|
||||
return true;
|
||||
}
|
||||
|
||||
void IActivate.Activate(ActivateEventArgs eventArgs)
|
||||
{
|
||||
NextState(eventArgs.User);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
using Content.Shared.MachineLinking;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.MachineLinking.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
public class TwoWayLeverComponent : Component
|
||||
{
|
||||
public override string Name => "TwoWayLever";
|
||||
|
||||
public TwoWayLeverSignal State;
|
||||
|
||||
public bool NextSignalLeft;
|
||||
}
|
||||
}
|
||||
16
Content.Server/MachineLinking/Events/InvokePortEvent.cs
Normal file
16
Content.Server/MachineLinking/Events/InvokePortEvent.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.MachineLinking.Events
|
||||
{
|
||||
public class InvokePortEvent : EntityEventArgs
|
||||
{
|
||||
public readonly string Port;
|
||||
public readonly object? Value;
|
||||
|
||||
public InvokePortEvent(string port, object? value = null)
|
||||
{
|
||||
Port = port;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
23
Content.Server/MachineLinking/Events/LinkAttemptEvent.cs
Normal file
23
Content.Server/MachineLinking/Events/LinkAttemptEvent.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using Content.Server.MachineLinking.Components;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.MachineLinking.Events
|
||||
{
|
||||
public class LinkAttemptEvent : CancellableEntityEventArgs
|
||||
{
|
||||
public readonly IEntity Attemptee;
|
||||
public readonly SignalTransmitterComponent TransmitterComponent;
|
||||
public readonly string TransmitterPort;
|
||||
public readonly SignalReceiverComponent ReceiverComponent;
|
||||
public readonly string ReceiverPort;
|
||||
|
||||
public LinkAttemptEvent(IEntity attemptee, SignalTransmitterComponent transmitterComponent, string transmitterPort, SignalReceiverComponent receiverComponent, string receiverPort)
|
||||
{
|
||||
TransmitterComponent = transmitterComponent;
|
||||
this.TransmitterPort = transmitterPort;
|
||||
ReceiverComponent = receiverComponent;
|
||||
this.ReceiverPort = receiverPort;
|
||||
Attemptee = attemptee;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.MachineLinking.Events
|
||||
{
|
||||
public class PortDisconnectedEvent : EntityEventArgs
|
||||
{
|
||||
public readonly string Port;
|
||||
|
||||
public PortDisconnectedEvent(string port)
|
||||
{
|
||||
Port = port;
|
||||
}
|
||||
}
|
||||
}
|
||||
16
Content.Server/MachineLinking/Events/SignalReceivedEvent.cs
Normal file
16
Content.Server/MachineLinking/Events/SignalReceivedEvent.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.MachineLinking.Events
|
||||
{
|
||||
public class SignalReceivedEvent : EntityEventArgs
|
||||
{
|
||||
public readonly string Port;
|
||||
public readonly object? Value;
|
||||
|
||||
public SignalReceivedEvent(string port, object? value)
|
||||
{
|
||||
Port = port;
|
||||
Value = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.MachineLinking.Events
|
||||
{
|
||||
public class SignalValueRequestedEvent : HandledEntityEventArgs
|
||||
{
|
||||
public readonly string Port;
|
||||
public readonly Type Type;
|
||||
|
||||
public object? Signal;
|
||||
|
||||
public SignalValueRequestedEvent(string port, Type type)
|
||||
{
|
||||
Port = port;
|
||||
Type = type;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace Content.Server.MachineLinking.Exceptions
|
||||
{
|
||||
public class InvalidPortValueException : Exception
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace Content.Server.MachineLinking.Exceptions
|
||||
{
|
||||
public class LinkAlreadyRegisteredException : Exception
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace Content.Server.MachineLinking.Exceptions
|
||||
{
|
||||
public class NoSignalValueProvidedException : Exception
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace Content.Server.MachineLinking.Exceptions
|
||||
{
|
||||
public class PortNotFoundException : Exception
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
20
Content.Server/MachineLinking/Models/SignalLink.cs
Normal file
20
Content.Server/MachineLinking/Models/SignalLink.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Content.Server.MachineLinking.Components;
|
||||
|
||||
namespace Content.Server.MachineLinking.Models
|
||||
{
|
||||
public 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
131
Content.Server/MachineLinking/Models/SignalLinkCollection.cs
Normal file
131
Content.Server/MachineLinking/Models/SignalLinkCollection.cs
Normal file
@@ -0,0 +1,131 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.MachineLinking.Components;
|
||||
using Content.Server.MachineLinking.Exceptions;
|
||||
|
||||
namespace Content.Server.MachineLinking.Models
|
||||
{
|
||||
public 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
81
Content.Server/MachineLinking/Models/SignalPort.cs
Normal file
81
Content.Server/MachineLinking/Models/SignalPort.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
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 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
using Content.Server.Administration;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server.MachineLinking
|
||||
{
|
||||
[AdminCommand(AdminFlags.Debug)]
|
||||
public class SignalLinkerCommand : IConsoleCommand
|
||||
{
|
||||
public string Command => "signallink";
|
||||
|
||||
public string Description => "Turns on signal linker mode. Click a transmitter to tune that signal and then click on each receiver to tune them to the transmitter signal.";
|
||||
|
||||
public string Help => "signallink (on/off)";
|
||||
|
||||
public void Execute(IConsoleShell shell, string argStr, string[] args)
|
||||
{
|
||||
var player = (IPlayerSession?) shell.Player;
|
||||
|
||||
if (player == null)
|
||||
{
|
||||
shell.WriteError("This command cannot be run locally.");
|
||||
return;
|
||||
}
|
||||
|
||||
bool? enable = null;
|
||||
if (args.Length > 0)
|
||||
{
|
||||
if (args[0] == "on")
|
||||
enable = true;
|
||||
else if (args[0] == "off")
|
||||
enable = false;
|
||||
else if (bool.TryParse(args[0], out var boolean))
|
||||
enable = boolean;
|
||||
else if (int.TryParse(args[0], out var num))
|
||||
{
|
||||
if (num == 1)
|
||||
enable = true;
|
||||
else if (num == 0)
|
||||
enable = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IoCManager.Resolve<IEntitySystemManager>().TryGetEntitySystem<SignalLinkerSystem>(out var system))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var ret = system.SignalLinkerKeybind(player.UserId, enable);
|
||||
shell.WriteLine(ret ? "Enabled" : "Disabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Server.Interaction;
|
||||
using Content.Server.MachineLinking.Components;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Input;
|
||||
using Robust.Shared.Input.Binding;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Players;
|
||||
|
||||
namespace Content.Server.MachineLinking
|
||||
{
|
||||
public class SignalLinkerSystem : EntitySystem
|
||||
{
|
||||
private readonly Dictionary<NetUserId, SignalTransmitterComponent?> _transmitters = new();
|
||||
|
||||
public bool SignalLinkerKeybind(NetUserId id, bool? enable)
|
||||
{
|
||||
enable ??= !_transmitters.ContainsKey(id);
|
||||
|
||||
if (enable.Value)
|
||||
{
|
||||
if (_transmitters.ContainsKey(id))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_transmitters.Count == 0)
|
||||
{
|
||||
CommandBinds.Builder
|
||||
.BindBefore(EngineKeyFunctions.Use,
|
||||
new PointerInputCmdHandler(HandleUse),
|
||||
typeof(InteractionSystem))
|
||||
.Register<SignalLinkerSystem>();
|
||||
}
|
||||
|
||||
_transmitters.Add(id, null);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!_transmitters.ContainsKey(id))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_transmitters.Remove(id);
|
||||
if (_transmitters.Count == 0)
|
||||
{
|
||||
CommandBinds.Unregister<SignalLinkerSystem>();
|
||||
}
|
||||
}
|
||||
|
||||
return enable.Value;
|
||||
}
|
||||
|
||||
private bool HandleUse(ICommonSession? session, EntityCoordinates coords, EntityUid uid)
|
||||
{
|
||||
if (session?.AttachedEntity == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_transmitters.TryGetValue(session.UserId, out var signalTransmitter))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!EntityManager.TryGetEntity(uid, out var entity))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (entity.TryGetComponent<SignalReceiverComponent>(out var signalReceiver))
|
||||
{
|
||||
if (signalReceiver.Interact(session.AttachedEntity, signalTransmitter))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (entity.TryGetComponent<SignalTransmitterComponent>(out var transmitter))
|
||||
{
|
||||
_transmitters[session.UserId] = transmitter.GetSignal(session.AttachedEntity);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
namespace Content.Server.MachineLinking.Signals
|
||||
{
|
||||
public struct ToggleSignal {}
|
||||
}
|
||||
23
Content.Server/MachineLinking/System/SignalButtonSystem.cs
Normal file
23
Content.Server/MachineLinking/System/SignalButtonSystem.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
using Content.Server.MachineLinking.Components;
|
||||
using Content.Server.MachineLinking.Events;
|
||||
using Content.Shared.Interaction;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.MachineLinking.System
|
||||
{
|
||||
public class SignalButtonSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<SignalButtonComponent, InteractHandEvent>(OnInteractHand);
|
||||
}
|
||||
|
||||
private void OnInteractHand(EntityUid uid, SignalButtonComponent component, InteractHandEvent args)
|
||||
{
|
||||
RaiseLocalEvent(uid, new InvokePortEvent("pressed"), false);
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
296
Content.Server/MachineLinking/System/SignalLinkerSystem.cs
Normal file
296
Content.Server/MachineLinking/System/SignalLinkerSystem.cs
Normal file
@@ -0,0 +1,296 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Content.Server.Hands.Components;
|
||||
using Content.Server.Interaction;
|
||||
using Content.Server.MachineLinking.Components;
|
||||
using Content.Server.MachineLinking.Events;
|
||||
using Content.Server.MachineLinking.Exceptions;
|
||||
using Content.Server.MachineLinking.Models;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Server.UserInterface;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.MachineLinking;
|
||||
using Content.Shared.Notification.Managers;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Server.Player;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.MachineLinking.System
|
||||
{
|
||||
public class SignalLinkerSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private IComponentManager _componentManager = default!;
|
||||
private InteractionSystem _interaction = default!;
|
||||
|
||||
private SignalLinkCollection _linkCollection = new();
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_interaction = Get<InteractionSystem>();
|
||||
|
||||
SubscribeLocalEvent<SignalTransmitterComponent, ComponentStartup>(TransmitterStartupHandler);
|
||||
SubscribeLocalEvent<SignalTransmitterComponent, InteractUsingEvent>(TransmitterInteractUsingHandler);
|
||||
SubscribeLocalEvent<SignalTransmitterComponent, InvokePortEvent>(OnTransmitterInvokePort);
|
||||
|
||||
SubscribeLocalEvent<SignalReceiverComponent, ComponentStartup>(OnReceiverStartup);
|
||||
SubscribeLocalEvent<SignalReceiverComponent, InteractUsingEvent>(OnReceiverInteractUsing);
|
||||
|
||||
SubscribeLocalEvent<SignalReceiverComponent, ComponentRemove>(OnReceiverRemoved);
|
||||
SubscribeLocalEvent<SignalTransmitterComponent, ComponentRemove>(OnTransmitterRemoved);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
if (!component.Outputs.TryGetPort(args.Port, out var port)) throw new PortNotFoundException();
|
||||
|
||||
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.Uid,
|
||||
new SignalReceivedEvent(link.Receiverport.Name, args.Value));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnReceiverInteractUsing(EntityUid uid, SignalReceiverComponent component, InteractUsingEvent args)
|
||||
{
|
||||
if (args.Handled) return;
|
||||
|
||||
if (!args.Used.TryGetComponent<SignalLinkerComponent>(out var linker) || !linker.Port.HasValue ||
|
||||
!args.User.TryGetComponent(out ActorComponent? actor) ||
|
||||
!linker.Port.Value.transmitter.Outputs.TryGetPort(linker.Port.Value.port, out var port))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (component.Inputs.Count == 1)
|
||||
{
|
||||
LinkerInteraction(args.User, linker.Port.Value.transmitter, linker.Port.Value.port, component,
|
||||
component.Inputs[0].Name);
|
||||
args.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var bui = component.Owner.GetUIOrNull(SignalReceiverUiKey.Key);
|
||||
if (bui == null)
|
||||
{
|
||||
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)
|
||||
{
|
||||
if (component.Owner.GetUIOrNull(SignalReceiverUiKey.Key) is { } ui)
|
||||
ui.OnReceiveMessage += msg => OnReceiverUIMessage(uid, component, msg);
|
||||
}
|
||||
|
||||
private void OnReceiverUIMessage(EntityUid uid, SignalReceiverComponent component,
|
||||
ServerBoundUserInterfaceMessage msg)
|
||||
{
|
||||
switch (msg.Message)
|
||||
{
|
||||
case SignalPortSelected portSelected:
|
||||
if (msg.Session.AttachedEntity == null ||
|
||||
!msg.Session.AttachedEntity.TryGetComponent(out HandsComponent? hands) ||
|
||||
!hands.TryGetActiveHeldEntity(out var heldEntity) ||
|
||||
!heldEntity.TryGetComponent(out SignalLinkerComponent? signalLinkerComponent) ||
|
||||
!_interaction.InRangeUnobstructed(msg.Session.AttachedEntity, component.Owner) ||
|
||||
!signalLinkerComponent.Port.HasValue ||
|
||||
!signalLinkerComponent.Port.Value.transmitter.Outputs.ContainsPort(signalLinkerComponent.Port
|
||||
.Value.port) || !component.Inputs.ContainsPort(portSelected.Port))
|
||||
return;
|
||||
LinkerInteraction(msg.Session.AttachedEntity, 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)
|
||||
{
|
||||
switch (msg.Message)
|
||||
{
|
||||
case SignalPortSelected portSelected:
|
||||
if (msg.Session.AttachedEntity == null ||
|
||||
!msg.Session.AttachedEntity.TryGetComponent(out HandsComponent? hands) ||
|
||||
!hands.TryGetActiveHeldEntity(out var heldEntity) ||
|
||||
!heldEntity.TryGetComponent(out SignalLinkerComponent? signalLinkerComponent) ||
|
||||
!_interaction.InRangeUnobstructed(msg.Session.AttachedEntity, component.Owner))
|
||||
return;
|
||||
LinkerSaveInteraction(msg.Session.AttachedEntity, signalLinkerComponent, component,
|
||||
portSelected.Port);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void TransmitterInteractUsingHandler(EntityUid uid, SignalTransmitterComponent component,
|
||||
InteractUsingEvent args)
|
||||
{
|
||||
if (args.Handled) return;
|
||||
|
||||
if (!args.Used.TryGetComponent<SignalLinkerComponent>(out var linker) ||
|
||||
!args.User.TryGetComponent(out ActorComponent? actor))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (component.Outputs.Count == 1)
|
||||
{
|
||||
var port = component.Outputs.First();
|
||||
LinkerSaveInteraction(args.User, linker, component, port.Name);
|
||||
args.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var bui = component.Owner.GetUIOrNull(SignalTransmitterUiKey.Key);
|
||||
if (bui == null) return;
|
||||
bui.Open(actor.PlayerSession);
|
||||
bui.SetState(new SignalPortsState(component.Outputs.GetPortStrings().ToArray()));
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void LinkerInteraction(IEntity entity, SignalTransmitterComponent transmitter, string transmitterPort,
|
||||
SignalReceiverComponent receiver, string receiverPort)
|
||||
{
|
||||
if (_linkCollection.LinkExists(transmitter, transmitterPort, receiver, receiverPort))
|
||||
{
|
||||
if (_linkCollection.RemoveLink(transmitter, transmitterPort, receiver, receiverPort))
|
||||
{
|
||||
RaiseLocalEvent(receiver.Owner.Uid, new PortDisconnectedEvent(receiverPort));
|
||||
RaiseLocalEvent(transmitter.Owner.Uid, 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.Uid, linkAttempt);
|
||||
RaiseLocalEvent(transmitter.Owner.Uid, linkAttempt);
|
||||
|
||||
if (linkAttempt.Cancelled) return;
|
||||
|
||||
var link = _linkCollection.AddLink(transmitter, transmitterPort, receiver, receiverPort);
|
||||
if (link.Transmitterport.Signal != null)
|
||||
RaiseLocalEvent(receiver.Owner.Uid,
|
||||
new SignalReceivedEvent(receiverPort, link.Transmitterport.Signal));
|
||||
|
||||
entity.PopupMessageCursor(Loc.GetString("signal-linker-component-linked-port", ("port", receiverPort),
|
||||
("machine", receiver)));
|
||||
}
|
||||
}
|
||||
|
||||
private void LinkerSaveInteraction(IEntity entity, SignalLinkerComponent linkerComponent,
|
||||
SignalTransmitterComponent transmitterComponent, string transmitterPort)
|
||||
{
|
||||
if (SavePortInSignalLinker(linkerComponent, transmitterComponent, transmitterPort))
|
||||
{
|
||||
entity.PopupMessageCursor(Loc.GetString("signal-linker-component-saved-port", ("port", transmitterPort),
|
||||
("machine", transmitterComponent.Owner)));
|
||||
}
|
||||
}
|
||||
|
||||
private bool SavePortInSignalLinker(SignalLinkerComponent linker, SignalTransmitterComponent transmitter,
|
||||
string port)
|
||||
{
|
||||
if (!transmitter.Outputs.ContainsPort(port)) return false;
|
||||
linker.Port = (transmitter, port);
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool IsInRange(SignalTransmitterComponent transmitterComponent,
|
||||
SignalReceiverComponent receiverComponent)
|
||||
{
|
||||
if (transmitterComponent.Owner.TryGetComponent<ApcPowerReceiverComponent>(
|
||||
out var transmitterPowerReceiverComponent) &&
|
||||
receiverComponent.Owner.TryGetComponent<ApcPowerReceiverComponent>(
|
||||
out var receiverPowerReceiverComponent)
|
||||
) //&& todo are they on the same powernet?
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return transmitterComponent.Owner.Transform.MapPosition.InRange(
|
||||
receiverComponent.Owner.Transform.MapPosition, 30f);
|
||||
}
|
||||
}
|
||||
}
|
||||
35
Content.Server/MachineLinking/System/SignalSwitchSystem.cs
Normal file
35
Content.Server/MachineLinking/System/SignalSwitchSystem.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using Content.Server.MachineLinking.Components;
|
||||
using Content.Server.MachineLinking.Events;
|
||||
using Content.Shared.Interaction;
|
||||
using Robust.Shared.GameObjects;
|
||||
|
||||
namespace Content.Server.MachineLinking.System
|
||||
{
|
||||
public class SignalSwitchSystem : EntitySystem
|
||||
{
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<SignalSwitchComponent, InteractHandEvent>(OnInteracted);
|
||||
SubscribeLocalEvent<SignalSwitchComponent, SignalValueRequestedEvent>(OnSignalValueRequested);
|
||||
}
|
||||
|
||||
private void OnSignalValueRequested(EntityUid uid, SignalSwitchComponent component, SignalValueRequestedEvent args)
|
||||
{
|
||||
if (args.Port == "state")
|
||||
{
|
||||
args.Handled = true;
|
||||
args.Signal = component.State;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnInteracted(EntityUid uid, SignalSwitchComponent component, InteractHandEvent args)
|
||||
{
|
||||
component.State = !component.State;
|
||||
RaiseLocalEvent(uid, new InvokePortEvent("state", component.State), false);
|
||||
RaiseLocalEvent(uid, new InvokePortEvent("stateChange"), false);
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
54
Content.Server/MachineLinking/System/TwoWayLeverSystem.cs
Normal file
54
Content.Server/MachineLinking/System/TwoWayLeverSystem.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using Content.Server.MachineLinking.Components;
|
||||
using Content.Server.MachineLinking.Events;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.MachineLinking;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
|
||||
namespace Content.Server.MachineLinking.System
|
||||
{
|
||||
public class TwoWayLeverSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IComponentManager _componentManager = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<TwoWayLeverComponent, InteractHandEvent>(OnInteractHand);
|
||||
SubscribeLocalEvent<TwoWayLeverComponent, SignalValueRequestedEvent>(OnSignalValueRequested);
|
||||
}
|
||||
|
||||
private void OnSignalValueRequested(EntityUid uid, TwoWayLeverComponent component, SignalValueRequestedEvent args)
|
||||
{
|
||||
args.Signal = component.State;
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnInteractHand(EntityUid uid, TwoWayLeverComponent component, InteractHandEvent args)
|
||||
{
|
||||
component.State = component.State switch
|
||||
{
|
||||
TwoWayLeverSignal.Middle => component.NextSignalLeft ? TwoWayLeverSignal.Left : TwoWayLeverSignal.Right,
|
||||
TwoWayLeverSignal.Right => TwoWayLeverSignal.Middle,
|
||||
TwoWayLeverSignal.Left => TwoWayLeverSignal.Middle,
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
if (component.State == TwoWayLeverSignal.Middle)
|
||||
{
|
||||
component.NextSignalLeft = !component.NextSignalLeft;
|
||||
}
|
||||
|
||||
if (_componentManager.TryGetComponent<AppearanceComponent>(uid, out var appearanceComponent))
|
||||
{
|
||||
appearanceComponent.SetData(TwoWayLeverVisuals.State, component.State);
|
||||
}
|
||||
|
||||
RaiseLocalEvent(uid, new InvokePortEvent("state", component.State));
|
||||
args.Handled = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,7 +13,7 @@ namespace Content.Shared.MachineLinking
|
||||
public enum TwoWayLeverSignal : byte
|
||||
{
|
||||
Middle,
|
||||
Left,
|
||||
Right
|
||||
Right,
|
||||
Left
|
||||
}
|
||||
}
|
||||
|
||||
17
Content.Shared/MachineLinking/UIKeys.cs
Normal file
17
Content.Shared/MachineLinking/UIKeys.cs
Normal file
@@ -0,0 +1,17 @@
|
||||
using System;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.MachineLinking
|
||||
{
|
||||
[Serializable, NetSerializable]
|
||||
public enum SignalTransmitterUiKey
|
||||
{
|
||||
Key
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum SignalReceiverUiKey
|
||||
{
|
||||
Key
|
||||
}
|
||||
}
|
||||
37
Content.Shared/MachineLinking/UIMessages.cs
Normal file
37
Content.Shared/MachineLinking/UIMessages.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared.MachineLinking
|
||||
{
|
||||
[Serializable, NetSerializable]
|
||||
public class SignalPortsState : BoundUserInterfaceState
|
||||
{
|
||||
/// <summary>
|
||||
/// A Dictionary containing all ports and wether or not they can be selected.
|
||||
/// </summary>
|
||||
public readonly Dictionary<string, bool> Ports;
|
||||
|
||||
public SignalPortsState(string[] ports) : this(ports.ToDictionary(s => s, _ => true))
|
||||
{
|
||||
}
|
||||
|
||||
public SignalPortsState(Dictionary<string, bool> ports)
|
||||
{
|
||||
Ports = ports;
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public class SignalPortSelected : BoundUserInterfaceMessage
|
||||
{
|
||||
public readonly string Port;
|
||||
|
||||
public SignalPortSelected(string port)
|
||||
{
|
||||
Port = port;
|
||||
}
|
||||
}
|
||||
}
|
||||
1
Resources/Locale/en-US/conveyors/conveyor-component.ftl
Normal file
1
Resources/Locale/en-US/conveyors/conveyor-component.ftl
Normal file
@@ -0,0 +1 @@
|
||||
conveyor-component-failed-link = The port shocks you as you try to connect to it!
|
||||
@@ -1,2 +0,0 @@
|
||||
signal-button-component-transmit-signal-success-message = Click
|
||||
signal-button-component-transmit-signal-no-receivers-message = No receivers connected.
|
||||
@@ -0,0 +1,10 @@
|
||||
signal-linker-component-saved-port = Successfully saved port '{$port}' of {$machine}!
|
||||
signal-linker-component-linked-port = Successfully linked saved port to port '{$port}' of {$machine}!
|
||||
signal-linker-component-unlinked-port = Successfully unlinked saved port from port '{$port}' of {$machine}!
|
||||
|
||||
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-type-mismatch = The port's type does not match the type of the saved port!
|
||||
|
||||
signal-linker-component-out-of-range = Connection is out of range!
|
||||
@@ -1,5 +0,0 @@
|
||||
signal-receiver-component-interact-no-transmitter-message = Signal not set.
|
||||
signal-receiver-component-interact-unlinked = Unlinked.
|
||||
signal-receiver-component-interact-out-of-range = Out of range.
|
||||
signal-receiver-component-interact-max-transmitters-limit = Max Transmitters reached!
|
||||
signal-receiver-component-interact-success = Linked!
|
||||
@@ -1,4 +0,0 @@
|
||||
signal-switch-component-transmit-no-receivers-connected = No receivers connected.
|
||||
|
||||
# ToggleSwitchVerb
|
||||
toggle-switch-verb-get-data-text = Toggle Switch
|
||||
@@ -1 +0,0 @@
|
||||
signal-transmitter-component-get-signal-success = Signal fetched.
|
||||
@@ -1 +0,0 @@
|
||||
signal-two-way-lever-component-next-state-no-receivers-connected = No receivers connected.
|
||||
@@ -28,6 +28,12 @@
|
||||
softness: 1.1
|
||||
offset: "0, -0.5"
|
||||
- type: SignalReceiver
|
||||
inputs:
|
||||
- name: toggle
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.SignalReceiverUiKey.Key
|
||||
type: SignalPortSelectorBoundUserInterface
|
||||
- type: Damageable
|
||||
resistances: metallicResistances
|
||||
- type: Destructible
|
||||
|
||||
@@ -12,6 +12,14 @@
|
||||
- type: SignalSwitch
|
||||
- type: Rotatable
|
||||
- type: SignalTransmitter
|
||||
outputs:
|
||||
- name: state
|
||||
type: bool
|
||||
- name: stateChange
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
- key: enum.SignalTransmitterUiKey.Key
|
||||
type: SignalPortSelectorBoundUserInterface
|
||||
placement:
|
||||
snap:
|
||||
- Wallmount
|
||||
@@ -30,6 +38,8 @@
|
||||
- type: SignalButton
|
||||
- type: Rotatable
|
||||
- type: SignalTransmitter
|
||||
outputs:
|
||||
- name: pressed
|
||||
placement:
|
||||
snap:
|
||||
- Wallmount
|
||||
|
||||
@@ -26,7 +26,10 @@
|
||||
state: conveyor_started_cw
|
||||
drawdepth: FloorObjects
|
||||
- type: SignalReceiver
|
||||
maxTransmitters: 1
|
||||
inputs:
|
||||
- name: state
|
||||
type: Content.Shared.MachineLinking.TwoWayLeverSignal
|
||||
maxConnections: 1
|
||||
- type: ApcPowerReceiver
|
||||
- type: Conveyor
|
||||
- type: Appearance
|
||||
@@ -69,6 +72,10 @@
|
||||
sprite: Structures/conveyor.rsi
|
||||
state: switch-off
|
||||
- type: TwoWayLever
|
||||
- type: SignalTransmitter
|
||||
outputs:
|
||||
- name: state
|
||||
type: Content.Shared.MachineLinking.TwoWayLeverSignal
|
||||
- type: Appearance
|
||||
visuals:
|
||||
- type: TwoWayLeverVisualizer
|
||||
|
||||
Reference in New Issue
Block a user