logic gate stuff (#16943)
Co-authored-by: deltanedas <@deltanedas:kde.org>
@@ -0,0 +1,36 @@
|
|||||||
|
using Content.Server.DeviceLinking.Systems;
|
||||||
|
using Content.Shared.DeviceLinking;
|
||||||
|
using Content.Shared.MachineLinking;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
|
namespace Content.Server.DeviceLinking.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An edge detector that pulses high or low output ports when the input port gets a rising or falling edge respectively.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
[Access(typeof(EdgeDetectorSystem))]
|
||||||
|
public sealed class EdgeDetectorComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the input port.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("inputPort", customTypeSerializer: typeof(PrototypeIdSerializer<SourcePortPrototype>))]
|
||||||
|
public string InputPort = "Input";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the rising edge output port.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("outputHighPort", customTypeSerializer: typeof(PrototypeIdSerializer<TransmitterPortPrototype>))]
|
||||||
|
public string OutputHighPort = "OutputHigh";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the falling edge output port.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("outputLowPort", customTypeSerializer: typeof(PrototypeIdSerializer<TransmitterPortPrototype>))]
|
||||||
|
public string OutputLowPort = "OutputLow";
|
||||||
|
|
||||||
|
// Initial state
|
||||||
|
[ViewVariables]
|
||||||
|
public SignalState State = SignalState.Low;
|
||||||
|
}
|
||||||
@@ -0,0 +1,73 @@
|
|||||||
|
using Content.Server.DeviceLinking.Systems;
|
||||||
|
using Content.Shared.DeviceLinking;
|
||||||
|
using Content.Shared.MachineLinking;
|
||||||
|
using Content.Shared.Tools;
|
||||||
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
|
namespace Content.Server.DeviceLinking.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A logic gate that sets its output port by doing an operation on its 2 input ports, A and B.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
[Access(typeof(LogicGateSystem))]
|
||||||
|
public sealed class LogicGateComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The logic gate operation to use.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("gate")]
|
||||||
|
public LogicGate Gate = LogicGate.Or;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tool quality to use for cycling logic gate operations.
|
||||||
|
/// Cannot be pulsing since linking uses that.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("cycleQuality", customTypeSerializer: typeof(PrototypeIdSerializer<ToolQualityPrototype>))]
|
||||||
|
public string CycleQuality = "Screwing";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sound played when cycling logic gate operations.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("cycleSound")]
|
||||||
|
public SoundSpecifier CycleSound = new SoundPathSpecifier("/Audio/Machines/lightswitch.ogg");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the first input port.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("inputPortA", customTypeSerializer: typeof(PrototypeIdSerializer<SourcePortPrototype>))]
|
||||||
|
public string InputPortA = "InputA";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the second input port.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("inputPortB", customTypeSerializer: typeof(PrototypeIdSerializer<SourcePortPrototype>))]
|
||||||
|
public string InputPortB = "InputB";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Name of the output port.
|
||||||
|
/// </summary>
|
||||||
|
[DataField("outputPort", customTypeSerializer: typeof(PrototypeIdSerializer<TransmitterPortPrototype>))]
|
||||||
|
public string OutputPort = "Output";
|
||||||
|
|
||||||
|
// Initial state
|
||||||
|
[ViewVariables]
|
||||||
|
public SignalState StateA = SignalState.Low;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
public SignalState StateB = SignalState.Low;
|
||||||
|
|
||||||
|
[ViewVariables]
|
||||||
|
public bool LastOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Last state of a signal port, used to not spam invoking ports.
|
||||||
|
/// </summary>
|
||||||
|
public enum SignalState : byte
|
||||||
|
{
|
||||||
|
Momentary, // Instantaneous pulse high, compatibility behavior
|
||||||
|
Low,
|
||||||
|
High
|
||||||
|
}
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
using Content.Server.MachineLinking.Events;
|
|
||||||
|
|
||||||
namespace Content.Server.DeviceLinking.Components;
|
|
||||||
|
|
||||||
[RegisterComponent]
|
|
||||||
public sealed class OrGateComponent : Component
|
|
||||||
{
|
|
||||||
// Initial state
|
|
||||||
[ViewVariables]
|
|
||||||
public SignalState StateA1 = SignalState.Low;
|
|
||||||
|
|
||||||
[ViewVariables]
|
|
||||||
public SignalState StateB1 = SignalState.Low;
|
|
||||||
|
|
||||||
[ViewVariables]
|
|
||||||
public SignalState LastO1 = SignalState.Low;
|
|
||||||
|
|
||||||
[ViewVariables]
|
|
||||||
public SignalState StateA2 = SignalState.Low;
|
|
||||||
|
|
||||||
[ViewVariables]
|
|
||||||
public SignalState StateB2 = SignalState.Low;
|
|
||||||
|
|
||||||
[ViewVariables]
|
|
||||||
public SignalState LastO2 = SignalState.Low;
|
|
||||||
}
|
|
||||||
|
|
||||||
public enum SignalState
|
|
||||||
{
|
|
||||||
Momentary, // Instantaneous pulse high, compatibility behavior
|
|
||||||
Low,
|
|
||||||
High
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -65,21 +65,21 @@ namespace Content.Server.DeviceLinking.Systems
|
|||||||
}
|
}
|
||||||
else if (args.Port == component.InBolt)
|
else if (args.Port == component.InBolt)
|
||||||
{
|
{
|
||||||
if (state == SignalState.High)
|
if (!TryComp<DoorBoltComponent>(uid, out var bolts))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// if its a pulse toggle, otherwise set bolts to high/low
|
||||||
|
bool bolt;
|
||||||
|
if (state == SignalState.Momentary)
|
||||||
{
|
{
|
||||||
if(TryComp<DoorBoltComponent>(uid, out var bolts))
|
bolt = !bolts.BoltsDown;
|
||||||
_bolts.SetBoltsWithAudio(uid, bolts, true);
|
|
||||||
}
|
|
||||||
else if (state == SignalState.Momentary)
|
|
||||||
{
|
|
||||||
if (TryComp<DoorBoltComponent>(uid, out var bolts))
|
|
||||||
_bolts.SetBoltsWithAudio(uid, bolts, newBolts: !bolts.BoltsDown);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(TryComp<DoorBoltComponent>(uid, out var bolts))
|
bolt = state == SignalState.High;
|
||||||
_bolts.SetBoltsWithAudio(uid, bolts, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_bolts.SetBoltsWithAudio(uid, bolts, bolt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
47
Content.Server/DeviceLinking/Systems/EdgeDetectorSystem.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using Content.Server.DeviceLinking.Components;
|
||||||
|
using Content.Server.DeviceNetwork;
|
||||||
|
using Content.Server.MachineLinking.Events;
|
||||||
|
using SignalReceivedEvent = Content.Server.DeviceLinking.Events.SignalReceivedEvent;
|
||||||
|
|
||||||
|
namespace Content.Server.DeviceLinking.Systems;
|
||||||
|
|
||||||
|
public sealed class EdgeDetectorSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly DeviceLinkSystem _deviceLink = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<EdgeDetectorComponent, ComponentInit>(OnInit);
|
||||||
|
SubscribeLocalEvent<EdgeDetectorComponent, SignalReceivedEvent>(OnSignalReceived);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInit(EntityUid uid, EdgeDetectorComponent comp, ComponentInit args)
|
||||||
|
{
|
||||||
|
_deviceLink.EnsureSinkPorts(uid, comp.InputPort);
|
||||||
|
_deviceLink.EnsureSourcePorts(uid, comp.OutputHighPort, comp.OutputLowPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSignalReceived(EntityUid uid, EdgeDetectorComponent comp, ref SignalReceivedEvent args)
|
||||||
|
{
|
||||||
|
// only handle signals with edges
|
||||||
|
var state = SignalState.Momentary;
|
||||||
|
if (args.Data == null ||
|
||||||
|
!args.Data.TryGetValue(DeviceNetworkConstants.LogicState, out state) ||
|
||||||
|
state == SignalState.Momentary)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (args.Port != comp.InputPort)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// make sure the level changed, multiple devices sending the same level are treated as one spamming
|
||||||
|
if (comp.State != state)
|
||||||
|
{
|
||||||
|
comp.State = state;
|
||||||
|
|
||||||
|
var port = state == SignalState.High ? comp.OutputHighPort : comp.OutputLowPort;
|
||||||
|
_deviceLink.InvokePort(uid, port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
133
Content.Server/DeviceLinking/Systems/LogicGateSystem.cs
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
using Content.Server.DeviceLinking.Components;
|
||||||
|
using Content.Server.DeviceNetwork;
|
||||||
|
using Content.Server.MachineLinking.Events;
|
||||||
|
using Content.Shared.DeviceLinking;
|
||||||
|
using Content.Shared.Examine;
|
||||||
|
using Content.Shared.Interaction;
|
||||||
|
using Content.Shared.Tools;
|
||||||
|
using Content.Shared.Popups;
|
||||||
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.Utility;
|
||||||
|
using SignalReceivedEvent = Content.Server.DeviceLinking.Events.SignalReceivedEvent;
|
||||||
|
|
||||||
|
namespace Content.Server.DeviceLinking.Systems;
|
||||||
|
|
||||||
|
public sealed class LogicGateSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly DeviceLinkSystem _deviceLink = default!;
|
||||||
|
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||||
|
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||||
|
[Dependency] private readonly SharedPopupSystem _popup = default!;
|
||||||
|
[Dependency] private readonly SharedToolSystem _tool = default!;
|
||||||
|
|
||||||
|
private readonly int GateCount = Enum.GetValues(typeof(LogicGate)).Length;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<LogicGateComponent, ComponentInit>(OnInit);
|
||||||
|
SubscribeLocalEvent<LogicGateComponent, ExaminedEvent>(OnExamined);
|
||||||
|
SubscribeLocalEvent<LogicGateComponent, InteractUsingEvent>(OnInteractUsing);
|
||||||
|
SubscribeLocalEvent<LogicGateComponent, SignalReceivedEvent>(OnSignalReceived);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInit(EntityUid uid, LogicGateComponent comp, ComponentInit args)
|
||||||
|
{
|
||||||
|
_deviceLink.EnsureSinkPorts(uid, comp.InputPortA, comp.InputPortB);
|
||||||
|
_deviceLink.EnsureSourcePorts(uid, comp.OutputPort);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnExamined(EntityUid uid, LogicGateComponent comp, ExaminedEvent args)
|
||||||
|
{
|
||||||
|
if (!args.IsInDetailsRange)
|
||||||
|
return;
|
||||||
|
|
||||||
|
args.PushMarkup(Loc.GetString("logic-gate-examine", ("gate", comp.Gate.ToString().ToUpper())));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInteractUsing(EntityUid uid, LogicGateComponent comp, InteractUsingEvent args)
|
||||||
|
{
|
||||||
|
if (args.Handled || !_tool.HasQuality(args.Used, comp.CycleQuality))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// cycle through possible gates
|
||||||
|
var gate = (int) comp.Gate;
|
||||||
|
gate = ++gate % GateCount;
|
||||||
|
comp.Gate = (LogicGate) gate;
|
||||||
|
|
||||||
|
// since gate changed the output probably has too, update it
|
||||||
|
UpdateOutput(uid, comp);
|
||||||
|
|
||||||
|
// notify the user
|
||||||
|
_audio.PlayPvs(comp.CycleSound, uid);
|
||||||
|
var msg = Loc.GetString("logic-gate-cycle", ("gate", comp.Gate.ToString().ToUpper()));
|
||||||
|
_popup.PopupEntity(msg, uid, args.User);
|
||||||
|
_appearance.SetData(uid, LogicGateVisuals.Gate, comp.Gate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSignalReceived(EntityUid uid, LogicGateComponent comp, ref SignalReceivedEvent args)
|
||||||
|
{
|
||||||
|
// default to momentary for compatibility with non-logic signals.
|
||||||
|
// currently only door status and logic gates have logic signal state.
|
||||||
|
var state = SignalState.Momentary;
|
||||||
|
args.Data?.TryGetValue(DeviceNetworkConstants.LogicState, out state);
|
||||||
|
|
||||||
|
// update the state for the correct port
|
||||||
|
if (args.Port == comp.InputPortA)
|
||||||
|
{
|
||||||
|
comp.StateA = state;
|
||||||
|
}
|
||||||
|
else if (args.Port == comp.InputPortB)
|
||||||
|
{
|
||||||
|
comp.StateB = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateOutput(uid, comp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handle the logic for a logic gate, invoking the port if the output changed.
|
||||||
|
/// </summary>
|
||||||
|
private void UpdateOutput(EntityUid uid, LogicGateComponent comp)
|
||||||
|
{
|
||||||
|
// get the new output value now that it's changed
|
||||||
|
var a = comp.StateA == SignalState.High;
|
||||||
|
var b = comp.StateB == SignalState.High;
|
||||||
|
var output = false;
|
||||||
|
switch (comp.Gate)
|
||||||
|
{
|
||||||
|
case LogicGate.Or:
|
||||||
|
output = a || b;
|
||||||
|
break;
|
||||||
|
case LogicGate.And:
|
||||||
|
output = a && b;
|
||||||
|
break;
|
||||||
|
case LogicGate.Xor:
|
||||||
|
output = a != b;
|
||||||
|
break;
|
||||||
|
case LogicGate.Nor:
|
||||||
|
output = !(a || b);
|
||||||
|
break;
|
||||||
|
case LogicGate.Nand:
|
||||||
|
output = !(a && b);
|
||||||
|
break;
|
||||||
|
case LogicGate.Xnor:
|
||||||
|
output = a == b;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only send a payload if it actually changed
|
||||||
|
if (output != comp.LastOutput)
|
||||||
|
{
|
||||||
|
comp.LastOutput = output;
|
||||||
|
|
||||||
|
var data = new NetworkPayload
|
||||||
|
{
|
||||||
|
[DeviceNetworkConstants.LogicState] = output ? SignalState.High : SignalState.Low
|
||||||
|
};
|
||||||
|
|
||||||
|
_deviceLink.InvokePort(uid, comp.OutputPort, data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
using Content.Server.DeviceLinking.Components;
|
|
||||||
using Content.Server.DeviceNetwork;
|
|
||||||
using Content.Server.MachineLinking.Events;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
using Robust.Shared.Utility;
|
|
||||||
using SignalReceivedEvent = Content.Server.DeviceLinking.Events.SignalReceivedEvent;
|
|
||||||
|
|
||||||
namespace Content.Server.DeviceLinking.Systems
|
|
||||||
{
|
|
||||||
[UsedImplicitly]
|
|
||||||
public sealed class OrGateSystem : EntitySystem
|
|
||||||
{
|
|
||||||
|
|
||||||
[Dependency] private readonly DeviceLinkSystem _signalSystem = default!;
|
|
||||||
|
|
||||||
public override void Initialize()
|
|
||||||
{
|
|
||||||
base.Initialize();
|
|
||||||
SubscribeLocalEvent<OrGateComponent, ComponentInit>(OnInit);
|
|
||||||
SubscribeLocalEvent<OrGateComponent, SignalReceivedEvent>(OnSignalReceived);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnInit(EntityUid uid, OrGateComponent component, ComponentInit args)
|
|
||||||
{
|
|
||||||
_signalSystem.EnsureSinkPorts(uid, "A1", "B1", "A2", "B2");
|
|
||||||
_signalSystem.EnsureSourcePorts(uid, "O1", "O2");
|
|
||||||
}
|
|
||||||
|
|
||||||
private void OnSignalReceived(EntityUid uid, OrGateComponent component, ref SignalReceivedEvent args)
|
|
||||||
{
|
|
||||||
var state = SignalState.Momentary;
|
|
||||||
args.Data?.TryGetValue(DeviceNetworkConstants.LogicState, out state);
|
|
||||||
|
|
||||||
switch (args.Port)
|
|
||||||
{
|
|
||||||
case "A1":
|
|
||||||
component.StateA1 = state;
|
|
||||||
break;
|
|
||||||
case "B1":
|
|
||||||
component.StateB1 = state;
|
|
||||||
break;
|
|
||||||
case "A2":
|
|
||||||
component.StateA2 = state;
|
|
||||||
break;
|
|
||||||
case "B2":
|
|
||||||
component.StateB2 = state;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// O1 = A1 || B1
|
|
||||||
var v1 = SignalState.Low;
|
|
||||||
if (component.StateA1 == SignalState.High || component.StateB1 == SignalState.High)
|
|
||||||
v1 = SignalState.High;
|
|
||||||
|
|
||||||
if (v1 != component.LastO1)
|
|
||||||
{
|
|
||||||
var data = new NetworkPayload
|
|
||||||
{
|
|
||||||
[DeviceNetworkConstants.LogicState] = v1
|
|
||||||
};
|
|
||||||
|
|
||||||
_signalSystem.InvokePort(uid, "O1", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
component.LastO1 = v1;
|
|
||||||
|
|
||||||
// O2 = A2 || B2
|
|
||||||
var v2 = SignalState.Low;
|
|
||||||
if (component.StateA2 == SignalState.High || component.StateB2 == SignalState.High)
|
|
||||||
v2 = SignalState.High;
|
|
||||||
|
|
||||||
if (v2 != component.LastO2)
|
|
||||||
{
|
|
||||||
var data = new NetworkPayload
|
|
||||||
{
|
|
||||||
[DeviceNetworkConstants.LogicState] = v2
|
|
||||||
};
|
|
||||||
|
|
||||||
_signalSystem.InvokePort(uid, "O2", data);
|
|
||||||
}
|
|
||||||
component.LastO2 = v2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
36
Content.Shared/DeviceLinking/SharedLogicGate.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using Robust.Shared.Serialization;
|
||||||
|
|
||||||
|
namespace Content.Shared.DeviceLinking;
|
||||||
|
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Types of logic gates that can be used, determines how the output port is set.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum LogicGate : byte
|
||||||
|
{
|
||||||
|
Or,
|
||||||
|
And,
|
||||||
|
Xor,
|
||||||
|
Nor,
|
||||||
|
Nand,
|
||||||
|
Xnor
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Tells clients which logic gate layer to draw.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum LogicGateVisuals : byte
|
||||||
|
{
|
||||||
|
Gate
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sprite layer for the logic gate.
|
||||||
|
/// </summary>
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum LogicGateLayers : byte
|
||||||
|
{
|
||||||
|
Gate
|
||||||
|
}
|
||||||
3
Resources/Locale/en-US/logic-gates/logic-gates.ftl
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
logic-gate-examine = It is currently {INDEFINITE($gate)} {$gate} gate.
|
||||||
|
|
||||||
|
logic-gate-cycle = Switched to {INDEFINITE($gate)} {$gate} gate
|
||||||
@@ -23,7 +23,7 @@ signal-port-name-close = Close
|
|||||||
signal-port-description-close = Closes a device.
|
signal-port-description-close = Closes a device.
|
||||||
|
|
||||||
signal-port-name-doorbolt = Door bolt
|
signal-port-name-doorbolt = Door bolt
|
||||||
signal-port-description-doorbolt = Toggles door bolt.
|
signal-port-description-doorbolt = Bolts door when HIGH.
|
||||||
|
|
||||||
signal-port-name-trigger = Trigger
|
signal-port-name-trigger = Trigger
|
||||||
signal-port-description-trigger = Triggers some mechanism on the device.
|
signal-port-description-trigger = Triggers some mechanism on the device.
|
||||||
@@ -69,3 +69,12 @@ signal-port-description-set-particle-epsilon = Sets the type of particle this de
|
|||||||
|
|
||||||
signal-port-name-set-particle-zeta = Set particle type: zeta
|
signal-port-name-set-particle-zeta = Set particle type: zeta
|
||||||
signal-port-description-set-particle-zeta = Sets the type of particle this device emits to zeta.
|
signal-port-description-set-particle-zeta = Sets the type of particle this device emits to zeta.
|
||||||
|
|
||||||
|
signal-port-name-logic-input-a = Input A
|
||||||
|
signal-port-description-logic-input-a = First input of a logic gate.
|
||||||
|
|
||||||
|
signal-port-name-logic-input-b = Input B
|
||||||
|
signal-port-description-logic-input-b = Second input of a logic gate.
|
||||||
|
|
||||||
|
signal-port-name-logic-input = Input
|
||||||
|
signal-port-description-logic-input = Input to the edge detector, cannot be a pulse signal.
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ signal-port-name-right = Right
|
|||||||
signal-port-description-right = This port is invoked whenever the lever is moved to the rightmost position.
|
signal-port-description-right = This port is invoked whenever the lever is moved to the rightmost position.
|
||||||
|
|
||||||
signal-port-name-doorstatus = Door status
|
signal-port-name-doorstatus = Door status
|
||||||
signal-port-description-doorstatus = This port is invoked whenever the door's status changes.
|
signal-port-description-doorstatus = This port is invoked with HIGH when the door opens and LOW when the door closes.
|
||||||
|
|
||||||
signal-port-name-middle = Middle
|
signal-port-name-middle = Middle
|
||||||
signal-port-description-middle = This port is invoked whenever the lever is moved to the neutral position.
|
signal-port-description-middle = This port is invoked whenever the lever is moved to the neutral position.
|
||||||
@@ -24,3 +24,12 @@ signal-port-description-timer-trigger = This port is invoked whenever the timer
|
|||||||
|
|
||||||
signal-port-name-timer-start = Timer Start
|
signal-port-name-timer-start = Timer Start
|
||||||
signal-port-description-timer-start = This port is invoked whenever the timer starts.
|
signal-port-description-timer-start = This port is invoked whenever the timer starts.
|
||||||
|
|
||||||
|
signal-port-name-logic-output = Output
|
||||||
|
signal-port-description-logic-output = This port is invoked with HIGH or LOW depending on the selected gate and inputs.
|
||||||
|
|
||||||
|
signal-port-name-logic-output-high = High Output
|
||||||
|
signal-port-description-logic-output-high = This port is invoked whenever the input has a rising edge.
|
||||||
|
|
||||||
|
signal-port-name-logic-output-low = Low Output
|
||||||
|
signal-port-description-logic-output-low = This port is invoked whenever the input has a falling edge.
|
||||||
|
|||||||
@@ -79,24 +79,19 @@
|
|||||||
description: signal-port-description-artifact-analyzer-receiver
|
description: signal-port-description-artifact-analyzer-receiver
|
||||||
|
|
||||||
- type: sinkPort
|
- type: sinkPort
|
||||||
id: A1
|
id: InputA
|
||||||
name: "Input A1"
|
name: signal-port-name-logic-input-a
|
||||||
description: "Input A1"
|
description: signal-port-description-logic-input-a
|
||||||
|
|
||||||
- type: sinkPort
|
- type: sinkPort
|
||||||
id: B1
|
id: InputB
|
||||||
name: "Input B1"
|
name: signal-port-name-logic-input-b
|
||||||
description: "Input B1"
|
description: signal-port-description-logic-input-b
|
||||||
|
|
||||||
- type: sinkPort
|
- type: sinkPort
|
||||||
id: A2
|
id: Input
|
||||||
name: "Input A2"
|
name: signal-port-name-logic-input
|
||||||
description: "Input A2"
|
description: signal-port-description-logic-input
|
||||||
|
|
||||||
- type: sinkPort
|
|
||||||
id: B2
|
|
||||||
name: "Input B2"
|
|
||||||
description: "Input B2"
|
|
||||||
|
|
||||||
- type: sinkPort
|
- type: sinkPort
|
||||||
id: SetParticleDelta
|
id: SetParticleDelta
|
||||||
|
|||||||
@@ -37,7 +37,8 @@
|
|||||||
- type: sourcePort
|
- type: sourcePort
|
||||||
id: DoorStatus
|
id: DoorStatus
|
||||||
name: signal-port-name-doorstatus
|
name: signal-port-name-doorstatus
|
||||||
description: signal-port-description-status
|
description: signal-port-description-doorstatus
|
||||||
|
defaultLinks: [ DoorBolt ]
|
||||||
|
|
||||||
- type: sourcePort
|
- type: sourcePort
|
||||||
id: OrderSender
|
id: OrderSender
|
||||||
@@ -74,11 +75,16 @@
|
|||||||
defaultLinks: [ Close, Off ]
|
defaultLinks: [ Close, Off ]
|
||||||
|
|
||||||
- type: sourcePort
|
- type: sourcePort
|
||||||
id: O1
|
id: Output
|
||||||
name: "Output 1"
|
name: signal-port-name-logic-output
|
||||||
description: "Output 1"
|
description: signal-port-description-logic-output
|
||||||
|
|
||||||
- type: sourcePort
|
- type: sourcePort
|
||||||
id: O2
|
id: OutputHigh
|
||||||
name: "Output 2"
|
name: signal-port-name-logic-output-high
|
||||||
description: "Output 2"
|
description: signal-port-description-logic-output-high
|
||||||
|
|
||||||
|
- type: sourcePort
|
||||||
|
id: OutputLow
|
||||||
|
name: signal-port-name-logic-output-low
|
||||||
|
description: signal-port-description-logic-output-low
|
||||||
|
|||||||
@@ -1,31 +1,68 @@
|
|||||||
- type: entity
|
- type: entity
|
||||||
id: OrGate
|
abstract: true
|
||||||
name: MS7432
|
|
||||||
description: Dual 2-Input OR Gate
|
|
||||||
parent: BaseItem
|
parent: BaseItem
|
||||||
placement:
|
id: BaseLogicItem
|
||||||
mode: SnapgridCenter
|
|
||||||
snap:
|
|
||||||
- Wallmount
|
|
||||||
components:
|
components:
|
||||||
- type: Anchorable
|
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Objects/Devices/gates.rsi
|
sprite: Objects/Devices/gates.rsi
|
||||||
state: or
|
- type: Anchorable
|
||||||
- type: Rotatable
|
- type: Rotatable
|
||||||
- type: OrGate
|
|
||||||
- type: DeviceNetwork
|
- type: DeviceNetwork
|
||||||
deviceNetId: Wireless
|
deviceNetId: Wireless
|
||||||
receiveFrequencyId: BasicDevice
|
receiveFrequencyId: BasicDevice
|
||||||
- type: WirelessNetworkConnection
|
- type: WirelessNetworkConnection
|
||||||
range: 200
|
range: 200
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: BaseLogicItem
|
||||||
|
id: LogicGate
|
||||||
|
name: logic gate
|
||||||
|
description: A logic gate with two inputs and one output. Technicians can change its mode of operation using a screwdriver.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
layers:
|
||||||
|
- state: base
|
||||||
|
- state: or
|
||||||
|
map: [ "enum.LogicGateLayers.Gate" ]
|
||||||
|
- type: LogicGate
|
||||||
- type: DeviceLinkSink
|
- type: DeviceLinkSink
|
||||||
ports:
|
ports:
|
||||||
- A1
|
- InputA
|
||||||
- B1
|
- InputB
|
||||||
- A2
|
|
||||||
- B2
|
|
||||||
- type: DeviceLinkSource
|
- type: DeviceLinkSource
|
||||||
ports:
|
ports:
|
||||||
- O1
|
- Output
|
||||||
- O2
|
- type: Construction
|
||||||
|
graph: LogicGate
|
||||||
|
node: logic_gate
|
||||||
|
- type: Appearance
|
||||||
|
- type: GenericVisualizer
|
||||||
|
visuals:
|
||||||
|
enum.LogicGateVisuals.Gate:
|
||||||
|
enum.LogicGateLayers.Gate:
|
||||||
|
Or: { state: or }
|
||||||
|
And: { state: and }
|
||||||
|
Xor: { state: xor }
|
||||||
|
Nor: { state: nor }
|
||||||
|
Nand: { state: nand }
|
||||||
|
Xnor: { state: xnor }
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: BaseLogicItem
|
||||||
|
id: EdgeDetector
|
||||||
|
name: edge detector
|
||||||
|
description: Splits rising and falling edges into unique pulses and detects how edgy you are.
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: edge_detector
|
||||||
|
- type: EdgeDetector
|
||||||
|
- type: DeviceLinkSink
|
||||||
|
ports:
|
||||||
|
- Input
|
||||||
|
- type: DeviceLinkSource
|
||||||
|
ports:
|
||||||
|
- OutputHigh
|
||||||
|
- OutputLow
|
||||||
|
- type: Construction
|
||||||
|
graph: LogicGate
|
||||||
|
node: edge_detector
|
||||||
|
|||||||
@@ -75,25 +75,20 @@
|
|||||||
|
|
||||||
- type: receiverPort
|
- type: receiverPort
|
||||||
id: DoorBolt
|
id: DoorBolt
|
||||||
name: "Bolt"
|
name: signal-port-name-doorbolt
|
||||||
description: "Bolt door when HIGH."
|
description: signal-port-description-doorbolt
|
||||||
|
|
||||||
- type: receiverPort
|
- type: receiverPort
|
||||||
id: A1
|
id: InputA
|
||||||
name: "Input A1"
|
name: signal-port-name-logic-input-a
|
||||||
description: "Input A1"
|
description: signal-port-description-logic-input-a
|
||||||
|
|
||||||
- type: receiverPort
|
- type: receiverPort
|
||||||
id: B1
|
id: InputB
|
||||||
name: "Input B1"
|
name: signal-port-name-logic-input-b
|
||||||
description: "Input B1"
|
description: signal-port-description-logic-input-b
|
||||||
|
|
||||||
- type: receiverPort
|
- type: receiverPort
|
||||||
id: A2
|
id: Input
|
||||||
name: "Input A2"
|
name: signal-port-name-logic-input
|
||||||
description: "Input A2"
|
description: signal-port-description-logic-input
|
||||||
|
|
||||||
- type: receiverPort
|
|
||||||
id: B2
|
|
||||||
name: "Input B2"
|
|
||||||
description: "Input B2"
|
|
||||||
|
|||||||
@@ -34,6 +34,12 @@
|
|||||||
description: signal-port-description-middle
|
description: signal-port-description-middle
|
||||||
defaultLinks: [ Off, Close ]
|
defaultLinks: [ Off, Close ]
|
||||||
|
|
||||||
|
- type: transmitterPort
|
||||||
|
id: DoorStatus
|
||||||
|
name: signal-port-name-doorstatus
|
||||||
|
description: signal-port-description-doorstatus
|
||||||
|
defaultLinks: [ DoorBolt ]
|
||||||
|
|
||||||
- type: transmitterPort
|
- type: transmitterPort
|
||||||
id: OrderSender
|
id: OrderSender
|
||||||
name: signal-port-name-order-sender
|
name: signal-port-name-order-sender
|
||||||
@@ -49,7 +55,7 @@
|
|||||||
id: MedicalScannerSender
|
id: MedicalScannerSender
|
||||||
name: signal-port-name-med-scanner-sender
|
name: signal-port-name-med-scanner-sender
|
||||||
description: signal-port-description-med-scanner-sender
|
description: signal-port-description-med-scanner-sender
|
||||||
|
|
||||||
- type: transmitterPort
|
- type: transmitterPort
|
||||||
id: Timer
|
id: Timer
|
||||||
name: signal-port-name-timer-trigger
|
name: signal-port-name-timer-trigger
|
||||||
@@ -69,16 +75,16 @@
|
|||||||
defaultLinks: [ ArtifactAnalyzerReceiver ]
|
defaultLinks: [ ArtifactAnalyzerReceiver ]
|
||||||
|
|
||||||
- type: transmitterPort
|
- type: transmitterPort
|
||||||
id: DoorStatus
|
id: Output
|
||||||
name: "Door Status"
|
name: signal-port-name-logic-output
|
||||||
description: "HIGH when door is open, LOW when door is closed."
|
description: signal-port-description-logic-output
|
||||||
|
|
||||||
- type: transmitterPort
|
- type: transmitterPort
|
||||||
id: O1
|
id: OutputHigh
|
||||||
name: "Output 1"
|
name: signal-port-name-logic-output-high
|
||||||
description: "Output 1"
|
description: signal-port-description-logic-output-high
|
||||||
|
|
||||||
- type: transmitterPort
|
- type: transmitterPort
|
||||||
id: O2
|
id: OutputLow
|
||||||
name: "Output 2"
|
name: signal-port-name-logic-output-low
|
||||||
description: "Output 2"
|
description: signal-port-description-logic-output-low
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
- type: constructionGraph
|
||||||
|
id: LogicGate
|
||||||
|
start: start
|
||||||
|
graph:
|
||||||
|
- node: start
|
||||||
|
edges:
|
||||||
|
- to: logic_gate
|
||||||
|
steps:
|
||||||
|
- material: Steel
|
||||||
|
amount: 3
|
||||||
|
doAfter: 1
|
||||||
|
- material: Cable
|
||||||
|
amount: 2
|
||||||
|
doAfter: 1
|
||||||
|
- to: edge_detector
|
||||||
|
steps:
|
||||||
|
- material: Steel
|
||||||
|
amount: 3
|
||||||
|
doAfter: 1
|
||||||
|
- material: Cable
|
||||||
|
amount: 2
|
||||||
|
doAfter: 1
|
||||||
|
- node: logic_gate
|
||||||
|
entity: LogicGate
|
||||||
|
- node: edge_detector
|
||||||
|
entity: EdgeDetector
|
||||||
@@ -8,3 +8,25 @@
|
|||||||
description: A torch fashioned from some wood.
|
description: A torch fashioned from some wood.
|
||||||
icon: { sprite: Objects/Misc/torch.rsi, state: icon }
|
icon: { sprite: Objects/Misc/torch.rsi, state: icon }
|
||||||
objectType: Item
|
objectType: Item
|
||||||
|
|
||||||
|
- type: construction
|
||||||
|
name: logic gate
|
||||||
|
id: LogicGate
|
||||||
|
graph: LogicGate
|
||||||
|
startNode: start
|
||||||
|
targetNode: logic_gate
|
||||||
|
category: construction-category-tools
|
||||||
|
description: A binary logic gate for signals.
|
||||||
|
icon: { sprite: Objects/Devices/gates.rsi, state: or_icon }
|
||||||
|
objectType: Item
|
||||||
|
|
||||||
|
- type: construction
|
||||||
|
name: edge detector
|
||||||
|
id: EdgeDetector
|
||||||
|
graph: LogicGate
|
||||||
|
startNode: start
|
||||||
|
targetNode: edge_detector
|
||||||
|
category: construction-category-tools
|
||||||
|
description: An edge detector for signals.
|
||||||
|
icon: { sprite: Objects/Devices/gates.rsi, state: edge_detector }
|
||||||
|
objectType: Item
|
||||||
|
|||||||
BIN
Resources/Textures/Objects/Devices/gates.rsi/and.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
Resources/Textures/Objects/Devices/gates.rsi/base.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
Resources/Textures/Objects/Devices/gates.rsi/edge_detector.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
@@ -1,14 +1,38 @@
|
|||||||
{
|
{
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"license": "CC-BY-SA-3.0",
|
"license": "CC-BY-SA-3.0",
|
||||||
"copyright": "Kevin Zheng 2022",
|
"copyright": "or.png originally created by Kevin Zheng, 2022. All are modified by deltanedas (github) for SS14, 2023.",
|
||||||
"size": {
|
"size": {
|
||||||
"x": 32,
|
"x": 32,
|
||||||
"y": 32
|
"y": 32
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "base"
|
||||||
},
|
},
|
||||||
"states": [
|
{
|
||||||
{
|
"name": "or"
|
||||||
"name": "or"
|
},
|
||||||
}
|
{
|
||||||
]
|
"name": "and"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "xor"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "nor"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "nand"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "xnor"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "edge_detector"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "or_icon"
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
BIN
Resources/Textures/Objects/Devices/gates.rsi/nand.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
Resources/Textures/Objects/Devices/gates.rsi/nor.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 7.2 KiB |
BIN
Resources/Textures/Objects/Devices/gates.rsi/or_icon.png
Normal file
|
After Width: | Height: | Size: 7.4 KiB |
BIN
Resources/Textures/Objects/Devices/gates.rsi/xnor.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
BIN
Resources/Textures/Objects/Devices/gates.rsi/xor.png
Normal file
|
After Width: | Height: | Size: 7.2 KiB |
@@ -53,7 +53,10 @@ FoodCondimentBottleSmallHotsauce: FoodCondimentBottleHotsauce
|
|||||||
FoodBakedCookieFortune: FoodSnackCookieFortune
|
FoodBakedCookieFortune: FoodSnackCookieFortune
|
||||||
GunSafeSubMachineGunVector: GunSafeSubMachineGunDrozd
|
GunSafeSubMachineGunVector: GunSafeSubMachineGunDrozd
|
||||||
|
|
||||||
|
# 2023-05-29
|
||||||
|
OrGate: null
|
||||||
|
|
||||||
# 2023-05-31
|
# 2023-05-31
|
||||||
IHSVoidsuit: null
|
IHSVoidsuit: null
|
||||||
ClothingHeadHelmetIHSVoidHelm: null
|
ClothingHeadHelmetIHSVoidHelm: null
|
||||||
ClothingHandsGlovesIhscombat: null
|
ClothingHandsGlovesIhscombat: null
|
||||||
|
|||||||