--- /dev/null
+using Content.Server.DeviceLinking.Systems;
+using Content.Shared.DeviceLinking;
+using Robust.Shared.Prototypes;
+
+namespace Content.Server.DeviceLinking.Components;
+
+/// <summary>
+/// Memory cell that sets the output to the input when enabled.
+/// </summary>
+[RegisterComponent, Access(typeof(MemoryCellSystem))]
+public sealed partial class MemoryCellComponent : Component
+{
+ /// <summary>
+ /// Name of the input port.
+ /// </summary>
+ [DataField]
+ public ProtoId<SinkPortPrototype> InputPort = "MemoryInput";
+
+ /// <summary>
+ /// Name of the enable port.
+ /// </summary>
+ [DataField]
+ public ProtoId<SinkPortPrototype> EnablePort = "MemoryEnable";
+
+ /// <summary>
+ /// Name of the output port.
+ /// </summary>
+ [DataField]
+ public ProtoId<SourcePortPrototype> OutputPort = "Output";
+
+ // State
+ [DataField]
+ public SignalState InputState = SignalState.Low;
+
+ [DataField]
+ public SignalState EnableState = SignalState.Low;
+
+ [DataField]
+ public bool LastOutput;
+}
--- /dev/null
+using Content.Server.DeviceLinking.Components;
+using Content.Server.DeviceLinking.Events;
+using Content.Server.DeviceNetwork;
+using Content.Shared.DeviceLinking;
+
+namespace Content.Server.DeviceLinking.Systems;
+
+/// <summary>
+/// Handles the control of output based on the input and enable ports.
+/// </summary>
+public sealed class MemoryCellSystem : EntitySystem
+{
+ [Dependency] private readonly DeviceLinkSystem _deviceLink = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent<MemoryCellComponent, ComponentInit>(OnInit);
+ SubscribeLocalEvent<MemoryCellComponent, SignalReceivedEvent>(OnSignalReceived);
+ }
+
+ public override void Update(float deltaTime)
+ {
+ base.Update(deltaTime);
+
+ var query = EntityQueryEnumerator<MemoryCellComponent, DeviceLinkSourceComponent>();
+ while (query.MoveNext(out var uid, out var comp, out var source))
+ {
+ if (comp.InputState == SignalState.Momentary)
+ comp.InputState = SignalState.Low;
+ if (comp.EnableState == SignalState.Momentary)
+ comp.EnableState = SignalState.Low;
+
+ UpdateOutput((uid, comp, source));
+ }
+ }
+
+ private void OnInit(Entity<MemoryCellComponent> ent, ref ComponentInit args)
+ {
+ var (uid, comp) = ent;
+ _deviceLink.EnsureSinkPorts(uid, comp.InputPort, comp.EnablePort);
+ _deviceLink.EnsureSourcePorts(uid, comp.OutputPort);
+ }
+
+ private void OnSignalReceived(Entity<MemoryCellComponent> ent, ref SignalReceivedEvent args)
+ {
+ var state = SignalState.Momentary;
+ args.Data?.TryGetValue(DeviceNetworkConstants.LogicState, out state);
+
+ if (args.Port == ent.Comp.InputPort)
+ ent.Comp.InputState = state;
+ else if (args.Port == ent.Comp.EnablePort)
+ ent.Comp.EnableState = state;
+
+ UpdateOutput(ent);
+ }
+
+ private void UpdateOutput(Entity<MemoryCellComponent, DeviceLinkSourceComponent?> ent)
+ {
+ if (!Resolve(ent, ref ent.Comp2))
+ return;
+
+ if (ent.Comp1.EnableState == SignalState.Low)
+ return;
+
+ var value = ent.Comp1.InputState != SignalState.Low;
+ if (value == ent.Comp1.LastOutput)
+ return;
+
+ ent.Comp1.LastOutput = value;
+ _deviceLink.SendSignal(ent, ent.Comp1.OutputPort, value, ent.Comp2);
+ }
+}
signal-port-name-logic-input = Input
signal-port-description-logic-input = Input to the edge detector, cannot be a pulse signal.
+
+signal-port-description-logic-memory-input = Signal to load into the memory cell, when enabled.
+
+signal-port-name-logic-enable = Enable
+signal-port-description-logic-enable = Only loads the input signal into the memory cell when HIGH.
name: signal-port-name-logic-input
description: signal-port-description-logic-input
+- type: sinkPort
+ id: MemoryInput
+ name: signal-port-name-logic-input
+ description: signal-port-description-logic-memory-input
+
+- type: sinkPort
+ id: MemoryEnable
+ name: signal-port-name-logic-enable
+ description: signal-port-description-logic-enable
+
- type: sinkPort
id: SetParticleDelta
name: signal-port-name-set-particle-delta
- type: entity
- abstract: true
parent: BaseItem
- id: BaseLogicItem
+ id: LogicEmptyCircuit
+ name: empty circuit
+ description: Something seems to be missing.
components:
- type: Sprite
sprite: Objects/Devices/gates.rsi
+ layers:
+ - state: base
- type: Anchorable
- type: Rotatable
+ - type: Construction
+ graph: LogicGate
+ node: empty
+
+- type: entity
+ abstract: true
+ parent: LogicEmptyCircuit
+ id: BaseLogicItem
+ components:
- type: DeviceNetwork
deviceNetId: Wireless
receiveFrequencyId: BasicDevice
- type: Sprite
layers:
- state: base
+ - state: logic
- state: or
map: [ "enum.LogicGateLayers.Gate" ]
- type: LogicGate
lastSignals:
Output: false
- type: Construction
- graph: LogicGate
node: logic_gate
- type: Appearance
- type: GenericVisualizer
description: Splits rising and falling edges into unique pulses and detects how edgy you are.
components:
- type: Sprite
- state: edge_detector
+ layers:
+ - state: base
+ - state: edge_detector
- type: EdgeDetector
- type: DeviceLinkSink
ports:
OutputHigh: false
OutputLow: false
- type: Construction
- graph: LogicGate
node: edge_detector
- type: entity
description: Generates signals in response to powernet changes. Can be cycled between cable voltages.
components:
- type: Sprite
- state: power_sensor
+ layers:
+ - state: base
+ - state: power_sensor
- type: PowerSensor
- type: PowerSwitchable
examineText: power-sensor-voltage-examine
PowerCharging: false
PowerDischarging: false
- type: Construction
- graph: LogicGate
node: power_sensor
+
+- type: entity
+ parent: BaseLogicItem
+ id: MemoryCell
+ name: memory cell
+ description: A D-Latch circuit that stores a signal which can be changed depending on input and enable ports.
+ components:
+ - type: Sprite
+ layers:
+ - state: base
+ - state: memory_cell
+ - type: MemoryCell
+ - type: DeviceLinkSink
+ ports:
+ - MemoryInput
+ - MemoryEnable
+ - type: DeviceLinkSource
+ ports:
+ - Output
+ - type: Construction
+ node: memory_cell
graph:
- node: start
edges:
- - to: logic_gate
+ - to: empty
steps:
- material: Steel
amount: 3
doAfter: 1
+ - node: empty
+ entity: LogicEmptyCircuit
+ edges:
+ - to: start
+ steps:
+ - tool: Screwing
+ doAfter: 2
+ completed:
+ - !type:SpawnPrototype
+ prototype: SheetSteel1
+ amount: 3
+ - !type:DeleteEntity {}
+ - to: logic_gate
+ steps:
- material: Cable
amount: 2
doAfter: 1
- to: edge_detector
steps:
- - material: Steel
- amount: 3
+ - material: Glass
+ amount: 2
doAfter: 1
- material: Cable
amount: 2
doAfter: 1
- to: power_sensor
steps:
- - material: Steel
- amount: 3
- doAfter: 1
- - material: Cable
- amount: 2
- doAfter: 1
- tag: Multitool
icon:
sprite: Objects/Tools/multitool.rsi
state: icon
name: a multitool
+ - material: Cable
+ amount: 2
+ doAfter: 1
+ - to: memory_cell
+ steps:
+ - tag: CapacitorStockPart
+ icon:
+ sprite: Objects/Misc/stock_parts.rsi
+ state: capacitor
+ name: a capacitor
+ - material: Cable
+ amount: 2
+ doAfter: 1
- node: logic_gate
entity: LogicGateOr
+ edges:
+ - to: empty
+ steps:
+ - tool: Prying
+ doAfter: 2
+ completed:
+ - !type:SpawnPrototype
+ prototype: CableApcStack1
+ amount: 2
- node: edge_detector
entity: EdgeDetector
+ edges:
+ - to: empty
+ steps:
+ - tool: Prying
+ doAfter: 2
+ completed:
+ - !type:SpawnPrototype
+ prototype: SheetGlass1
+ amount: 2
+ - !type:SpawnPrototype
+ prototype: CableApcStack1
+ amount: 2
- node: power_sensor
entity: PowerSensor
+ edges:
+ - to: empty
+ steps:
+ - tool: Prying
+ doAfter: 2
+ completed:
+ - !type:SpawnPrototype
+ prototype: Multitool
+ - !type:SpawnPrototype
+ prototype: CableApcStack1
+ amount: 2
+ - node: memory_cell
+ entity: MemoryCell
+ edges:
+ - to: empty
+ steps:
+ - tool: Prying
+ doAfter: 2
+ completed:
+ - !type:SpawnPrototype
+ prototype: CapacitorStockPart
+ - !type:SpawnPrototype
+ prototype: CableApcStack1
+ amount: 2
description: A power network checking device for signals.
icon: { sprite: Objects/Devices/gates.rsi, state: power_sensor }
objectType: Item
+
+- type: construction
+ name: memory cell
+ id: MemoryCell
+ graph: LogicGate
+ startNode: start
+ targetNode: memory_cell
+ category: construction-category-tools
+ description: A memory cell for signals.
+ icon: { sprite: Objects/Devices/gates.rsi, state: memory_cell }
+ objectType: Item
{
"version": 1,
"license": "CC-BY-SA-3.0",
- "copyright": "or.png originally created by Kevin Zheng, 2022. All are modified by deltanedas (github) for SS14, 2023.",
+ "copyright": "or.png originally created by Kevin Zheng, 2022. All are modified by deltanedas (github) for SS14, 2024.",
"size": {
"x": 32,
"y": 32
{
"name": "base"
},
+ {
+ "name": "logic"
+ },
{
"name": "or"
},
},
{
"name": "power_sensor"
+ },
+ {
+ "name": "memory_cell"
}
]
}