Machine Port Prototypes (#7659)
Co-authored-by: metalgearsloth <comedian_vs_clown@hotmail.com>
This commit is contained in:
@@ -7,9 +7,9 @@ using Content.Shared.Interaction;
|
||||
using Content.Shared.MachineLinking;
|
||||
using Content.Shared.Popups;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Utility;
|
||||
using Robust.Shared.Player;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Content.Shared.MachineLinking.Events;
|
||||
|
||||
namespace Content.Server.MachineLinking.System
|
||||
@@ -18,24 +18,12 @@ namespace Content.Server.MachineLinking.System
|
||||
{
|
||||
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
|
||||
[Dependency] private readonly SharedPopupSystem _popupSystem = default!;
|
||||
|
||||
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") },
|
||||
};
|
||||
[Dependency] private readonly IPrototypeManager _protoMan = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<SignalTransmitterComponent, InvokePortEvent>(OnTransmitterInvokePort);
|
||||
|
||||
SubscribeLocalEvent<SignalTransmitterComponent, ComponentStartup>(OnTransmitterStartup);
|
||||
SubscribeLocalEvent<SignalTransmitterComponent, ComponentRemove>(OnTransmitterRemoved);
|
||||
SubscribeLocalEvent<SignalTransmitterComponent, InteractUsingEvent>(OnTransmitterInteractUsing);
|
||||
@@ -52,6 +40,27 @@ namespace Content.Server.MachineLinking.System
|
||||
SubscribeLocalEvent<SignalLinkerComponent, BoundUIClosedEvent>(OnLinkerUIClosed);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convenience function to add several ports to an entity.
|
||||
/// </summary>
|
||||
public void EnsureReceiverPorts(EntityUid uid, params string[] ports)
|
||||
{
|
||||
var comp = EnsureComp<SignalReceiverComponent>(uid);
|
||||
foreach (var port in ports)
|
||||
{
|
||||
comp.Inputs.TryAdd(port, new());
|
||||
}
|
||||
}
|
||||
|
||||
public void EnsureTransmitterPorts(EntityUid uid, params string[] ports)
|
||||
{
|
||||
var comp = EnsureComp<SignalTransmitterComponent>(uid);
|
||||
foreach (var port in ports)
|
||||
{
|
||||
comp.Outputs.TryAdd(port, new());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add an alt-click verb to allow users to link the default ports, without needing to open the UI.
|
||||
/// </summary>
|
||||
@@ -117,9 +126,15 @@ namespace Content.Server.MachineLinking.System
|
||||
verb.Message = Loc.GetString("signal-linking-verb-disabled-no-receiver");
|
||||
}
|
||||
|
||||
private void OnTransmitterInvokePort(EntityUid uid, SignalTransmitterComponent component, InvokePortEvent args)
|
||||
public void InvokePort(EntityUid uid, string port, SignalTransmitterComponent? component = null)
|
||||
{
|
||||
foreach (var receiver in component.Outputs[args.Port])
|
||||
if (!Resolve(uid, ref component))
|
||||
return;
|
||||
|
||||
if (!component.Outputs.TryGetValue(port, out var receivers))
|
||||
return;
|
||||
|
||||
foreach (var receiver in receivers)
|
||||
RaiseLocalEvent(receiver.Uid, new SignalReceivedEvent(receiver.Port), false);
|
||||
}
|
||||
|
||||
@@ -264,10 +279,18 @@ namespace Content.Server.MachineLinking.System
|
||||
|
||||
private bool TryLink(SignalTransmitterComponent transmitter, SignalReceiverComponent receiver, SignalPortSelected args, EntityUid user, bool quiet = false, bool checkRange = true)
|
||||
{
|
||||
if (!transmitter.Outputs.TryGetValue(args.TransmitterPort, out var receivers) ||
|
||||
!receiver.Inputs.TryGetValue(args.ReceiverPort, out var transmitters))
|
||||
if (!transmitter.Outputs.TryGetValue(args.TransmitterPort, out var linkedReceivers) ||
|
||||
!receiver.Inputs.TryGetValue(args.ReceiverPort, out var linkedTransmitters))
|
||||
return false;
|
||||
|
||||
// Does the link already exist? Under the assumption that nothing has broken, lets only check the
|
||||
// transmitter ports.
|
||||
foreach (var identifier in linkedTransmitters)
|
||||
{
|
||||
if (identifier.Uid == transmitter.Owner && identifier.Port == args.TransmitterPort)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (checkRange && !IsInRange(transmitter, receiver))
|
||||
{
|
||||
if (!quiet)
|
||||
@@ -295,12 +318,12 @@ namespace Content.Server.MachineLinking.System
|
||||
return false;
|
||||
}
|
||||
|
||||
receivers.Add(new(receiver.Owner, args.ReceiverPort));
|
||||
transmitters.Add(new(transmitter.Owner, args.TransmitterPort));
|
||||
linkedReceivers.Add(new(receiver.Owner, args.ReceiverPort));
|
||||
linkedTransmitters.Add(new(transmitter.Owner, args.TransmitterPort));
|
||||
if (!quiet)
|
||||
_popupSystem.PopupCursor(Loc.GetString("signal-linker-component-linked-port",
|
||||
("machine1", transmitter.Owner), ("port1", args.TransmitterPort),
|
||||
("machine2", receiver.Owner), ("port2", args.ReceiverPort)),
|
||||
("machine1", transmitter.Owner), ("port1", PortName<TransmitterPortPrototype>(args.TransmitterPort)),
|
||||
("machine2", receiver.Owner), ("port2", PortName<ReceiverPortPrototype>(args.ReceiverPort))),
|
||||
Filter.Entities(user));
|
||||
|
||||
return true;
|
||||
@@ -326,8 +349,8 @@ namespace Content.Server.MachineLinking.System
|
||||
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)),
|
||||
("machine1", transmitter.Owner), ("port1", PortName<TransmitterPortPrototype>(args.TransmitterPort)),
|
||||
("machine2", receiver.Owner), ("port2", PortName<ReceiverPortPrototype>(args.ReceiverPort))),
|
||||
Filter.Entities(attached));
|
||||
}
|
||||
else
|
||||
@@ -343,6 +366,19 @@ namespace Content.Server.MachineLinking.System
|
||||
TryUpdateUI(linker, transmitter, receiver);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convenience function to retrieve the name of a port prototype.
|
||||
/// </summary>
|
||||
/// <param name="port"></param>
|
||||
/// <returns></returns>
|
||||
public string PortName<TPort>(string port) where TPort : MachinePortPrototype, IPrototype
|
||||
{
|
||||
if (!_protoMan.TryIndex<TPort>(port, out var proto))
|
||||
return port;
|
||||
|
||||
return Loc.GetString(proto.Name);
|
||||
}
|
||||
|
||||
private void OnLinkerClearSelected(EntityUid uid, SignalLinkerComponent linker, LinkerClearSelected args)
|
||||
{
|
||||
if (!TryComp(linker.SavedTransmitter, out SignalTransmitterComponent? transmitter) ||
|
||||
@@ -388,19 +424,27 @@ namespace Content.Server.MachineLinking.System
|
||||
|
||||
var allLinksSucceeded = true;
|
||||
|
||||
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))
|
||||
// First, disconnect existing links.
|
||||
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));
|
||||
|
||||
// Then make any valid default connections.
|
||||
foreach (var outPort in transmitter.Outputs.Keys)
|
||||
{
|
||||
foreach (var (port, receivers) in transmitter.Outputs)
|
||||
if (receivers.RemoveAll(id => id.Uid == receiver.Owner) > 0)
|
||||
RaiseLocalEvent(transmitter.Owner, new PortDisconnectedEvent(port));
|
||||
var prototype = _protoMan.Index<TransmitterPortPrototype>(outPort);
|
||||
if (prototype.DefaultLinks == null)
|
||||
continue;
|
||||
|
||||
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)
|
||||
allLinksSucceeded &= !TryLink(transmitter, receiver, new(t, r), user, quiet: true, checkRange: false);
|
||||
foreach (var inPort in prototype.DefaultLinks)
|
||||
{
|
||||
if (receiver.Inputs.ContainsKey(inPort))
|
||||
allLinksSucceeded &= TryLink(transmitter, receiver, new(outPort, inPort), user, quiet: true, checkRange: false);
|
||||
}
|
||||
}
|
||||
|
||||
return allLinksSucceeded;
|
||||
|
||||
Reference in New Issue
Block a user