Add device linking to emitter and APE (#16805)

This commit is contained in:
0x6273
2023-05-28 08:44:28 +02:00
committed by GitHub
parent 7594dabe14
commit 7a5a64ffb4
7 changed files with 160 additions and 44 deletions

View File

@@ -1,10 +1,10 @@
using System.Threading; using System.Threading;
using Content.Server.Administration.Logs; using Content.Server.Administration.Logs;
using Content.Server.Construction; using Content.Server.Construction;
using Content.Server.DeviceLinking.Events;
using Content.Server.Power.Components; using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems; using Content.Server.Power.EntitySystems;
using Content.Server.Projectiles; using Content.Server.Projectiles;
using Content.Server.Storage.Components;
using Content.Server.Weapons.Ranged.Systems; using Content.Server.Weapons.Ranged.Systems;
using Content.Shared.Database; using Content.Shared.Database;
using Content.Shared.Examine; using Content.Shared.Examine;
@@ -50,6 +50,7 @@ namespace Content.Server.Singularity.EntitySystems
SubscribeLocalEvent<EmitterComponent, RefreshPartsEvent>(OnRefreshParts); SubscribeLocalEvent<EmitterComponent, RefreshPartsEvent>(OnRefreshParts);
SubscribeLocalEvent<EmitterComponent, UpgradeExamineEvent>(OnUpgradeExamine); SubscribeLocalEvent<EmitterComponent, UpgradeExamineEvent>(OnUpgradeExamine);
SubscribeLocalEvent<EmitterComponent, AnchorStateChangedEvent>(OnAnchorStateChanged); SubscribeLocalEvent<EmitterComponent, AnchorStateChangedEvent>(OnAnchorStateChanged);
SubscribeLocalEvent<EmitterComponent, SignalReceivedEvent>(OnSignalReceived);
} }
private void OnAnchorStateChanged(EntityUid uid, EmitterComponent component, ref AnchorStateChangedEvent args) private void OnAnchorStateChanged(EntityUid uid, EmitterComponent component, ref AnchorStateChangedEvent args)
@@ -57,7 +58,7 @@ namespace Content.Server.Singularity.EntitySystems
if (args.Anchored) if (args.Anchored)
return; return;
SwitchOff(component); SwitchOff(uid, component);
} }
private void OnInteractHand(EntityUid uid, EmitterComponent component, InteractHandEvent args) private void OnInteractHand(EntityUid uid, EmitterComponent component, InteractHandEvent args)
@@ -65,26 +66,26 @@ namespace Content.Server.Singularity.EntitySystems
if (args.Handled) if (args.Handled)
return; return;
if (EntityManager.TryGetComponent(uid, out LockComponent? lockComp) && lockComp.Locked) if (TryComp(uid, out LockComponent? lockComp) && lockComp.Locked)
{ {
_popup.PopupEntity(Loc.GetString("comp-emitter-access-locked", _popup.PopupEntity(Loc.GetString("comp-emitter-access-locked",
("target", component.Owner)), uid, args.User); ("target", uid)), uid, args.User);
return; return;
} }
if (EntityManager.TryGetComponent(component.Owner, out PhysicsComponent? phys) && phys.BodyType == BodyType.Static) if (TryComp(uid, out PhysicsComponent? phys) && phys.BodyType == BodyType.Static)
{ {
if (!component.IsOn) if (!component.IsOn)
{ {
SwitchOn(component); SwitchOn(uid, component);
_popup.PopupEntity(Loc.GetString("comp-emitter-turned-on", _popup.PopupEntity(Loc.GetString("comp-emitter-turned-on",
("target", component.Owner)), uid, args.User); ("target", uid)), uid, args.User);
} }
else else
{ {
SwitchOff(component); SwitchOff(uid, component);
_popup.PopupEntity(Loc.GetString("comp-emitter-turned-off", _popup.PopupEntity(Loc.GetString("comp-emitter-turned-off",
("target", component.Owner)), uid, args.User); ("target", uid)), uid, args.User);
} }
_adminLogger.Add(LogType.Emitter, _adminLogger.Add(LogType.Emitter,
@@ -95,7 +96,7 @@ namespace Content.Server.Singularity.EntitySystems
else else
{ {
_popup.PopupEntity(Loc.GetString("comp-emitter-not-anchored", _popup.PopupEntity(Loc.GetString("comp-emitter-not-anchored",
("target", component.Owner)), uid, args.User); ("target", uid)), uid, args.User);
} }
} }
@@ -152,11 +153,11 @@ namespace Content.Server.Singularity.EntitySystems
if (args.ReceivedPower < args.DrawRate) if (args.ReceivedPower < args.DrawRate)
{ {
PowerOff(component); PowerOff(uid, component);
} }
else else
{ {
PowerOn(component); PowerOn(uid, component);
} }
} }
@@ -169,11 +170,11 @@ namespace Content.Server.Singularity.EntitySystems
if (!args.Powered) if (!args.Powered)
{ {
PowerOff(component); PowerOff(uid, component);
} }
else else
{ {
PowerOn(component); PowerOn(uid, component);
} }
} }
@@ -191,33 +192,33 @@ namespace Content.Server.Singularity.EntitySystems
args.AddPercentageUpgrade("emitter-component-upgrade-fire-rate", (float) (component.BaseFireInterval.TotalSeconds / component.FireInterval.TotalSeconds)); args.AddPercentageUpgrade("emitter-component-upgrade-fire-rate", (float) (component.BaseFireInterval.TotalSeconds / component.FireInterval.TotalSeconds));
} }
public void SwitchOff(EmitterComponent component) public void SwitchOff(EntityUid uid, EmitterComponent component)
{ {
component.IsOn = false; component.IsOn = false;
if (TryComp<PowerConsumerComponent>(component.Owner, out var powerConsumer)) if (TryComp<PowerConsumerComponent>(uid, out var powerConsumer))
powerConsumer.DrawRate = 1; // this needs to be not 0 so that the visuals still work. powerConsumer.DrawRate = 1; // this needs to be not 0 so that the visuals still work.
if (TryComp<ApcPowerReceiverComponent>(component.Owner, out var apcReceiever)) if (TryComp<ApcPowerReceiverComponent>(uid, out var apcReceiver))
apcReceiever.Load = 1; apcReceiver.Load = 1;
PowerOff(component); PowerOff(uid, component);
UpdateAppearance(component); UpdateAppearance(uid, component);
} }
public void SwitchOn(EmitterComponent component) public void SwitchOn(EntityUid uid, EmitterComponent component)
{ {
component.IsOn = true; component.IsOn = true;
if (TryComp<PowerConsumerComponent>(component.Owner, out var powerConsumer)) if (TryComp<PowerConsumerComponent>(uid, out var powerConsumer))
powerConsumer.DrawRate = component.PowerUseActive; powerConsumer.DrawRate = component.PowerUseActive;
if (TryComp<ApcPowerReceiverComponent>(component.Owner, out var apcReceiever)) if (TryComp<ApcPowerReceiverComponent>(uid, out var apcReceiver))
{ {
apcReceiever.Load = component.PowerUseActive; apcReceiver.Load = component.PowerUseActive;
PowerOn(component); PowerOn(uid, component);
} }
// Do not directly PowerOn(). // Do not directly PowerOn().
// OnReceivedPowerChanged will get fired due to DrawRate change which will turn it on. // OnReceivedPowerChanged will get fired due to DrawRate change which will turn it on.
UpdateAppearance(component); UpdateAppearance(uid, component);
} }
public void PowerOff(EmitterComponent component) public void PowerOff(EntityUid uid, EmitterComponent component)
{ {
if (!component.IsPowered) if (!component.IsPowered)
{ {
@@ -230,10 +231,10 @@ namespace Content.Server.Singularity.EntitySystems
DebugTools.AssertNotNull(component.TimerCancel); DebugTools.AssertNotNull(component.TimerCancel);
component.TimerCancel?.Cancel(); component.TimerCancel?.Cancel();
UpdateAppearance(component); UpdateAppearance(uid, component);
} }
public void PowerOn(EmitterComponent component) public void PowerOn(EntityUid uid, EmitterComponent component)
{ {
if (component.IsPowered) if (component.IsPowered)
{ {
@@ -245,12 +246,12 @@ namespace Content.Server.Singularity.EntitySystems
component.FireShotCounter = 0; component.FireShotCounter = 0;
component.TimerCancel = new CancellationTokenSource(); component.TimerCancel = new CancellationTokenSource();
Timer.Spawn(component.FireBurstDelayMax, () => ShotTimerCallback(component), component.TimerCancel.Token); Timer.Spawn(component.FireBurstDelayMax, () => ShotTimerCallback(uid, component), component.TimerCancel.Token);
UpdateAppearance(component); UpdateAppearance(uid, component);
} }
private void ShotTimerCallback(EmitterComponent component) private void ShotTimerCallback(EntityUid uid, EmitterComponent component)
{ {
if (component.Deleted) if (component.Deleted)
return; return;
@@ -260,7 +261,7 @@ namespace Content.Server.Singularity.EntitySystems
DebugTools.Assert(component.IsPowered); DebugTools.Assert(component.IsPowered);
DebugTools.Assert(component.IsOn); DebugTools.Assert(component.IsOn);
Fire(component); Fire(uid, component);
TimeSpan delay; TimeSpan delay;
if (component.FireShotCounter < component.FireBurstSize) if (component.FireShotCounter < component.FireBurstSize)
@@ -278,13 +279,12 @@ namespace Content.Server.Singularity.EntitySystems
// Must be set while emitter powered. // Must be set while emitter powered.
DebugTools.AssertNotNull(component.TimerCancel); DebugTools.AssertNotNull(component.TimerCancel);
Timer.Spawn(delay, () => ShotTimerCallback(component), component.TimerCancel!.Token); Timer.Spawn(delay, () => ShotTimerCallback(uid, component), component.TimerCancel!.Token);
} }
private void Fire(EmitterComponent component) private void Fire(EntityUid uid, EmitterComponent component)
{ {
var uid = component.Owner; if (!TryComp<GunComponent>(uid, out var gunComponent))
if (!TryComp<GunComponent>(uid, out var guncomp))
return; return;
var xform = Transform(uid); var xform = Transform(uid);
@@ -293,10 +293,11 @@ namespace Content.Server.Singularity.EntitySystems
_projectile.SetShooter(proj, uid); _projectile.SetShooter(proj, uid);
var targetPos = new EntityCoordinates(uid, (0, -1)); var targetPos = new EntityCoordinates(uid, (0, -1));
_gun.Shoot(uid, guncomp, ent, xform.Coordinates, targetPos, out _);
_gun.Shoot(uid, gunComponent, ent, xform.Coordinates, targetPos, out _);
} }
private void UpdateAppearance(EmitterComponent component) private void UpdateAppearance(EntityUid uid, EmitterComponent component)
{ {
EmitterVisualState state; EmitterVisualState state;
if (component.IsPowered) if (component.IsPowered)
@@ -311,7 +312,34 @@ namespace Content.Server.Singularity.EntitySystems
{ {
state = EmitterVisualState.Off; state = EmitterVisualState.Off;
} }
_appearance.SetData(component.Owner, EmitterVisuals.VisualState, state); _appearance.SetData(uid, EmitterVisuals.VisualState, state);
}
private void OnSignalReceived(EntityUid uid, EmitterComponent component, ref SignalReceivedEvent args)
{
if (args.Port == component.OffPort)
{
SwitchOff(uid, component);
}
else if (args.Port == component.OnPort)
{
SwitchOn(uid, component);
}
else if (args.Port == component.TogglePort)
{
if (component.IsOn)
{
SwitchOff(uid, component);
}
else
{
SwitchOn(uid, component);
}
}
else if (component.SetTypePorts.TryGetValue(args.Port, out var boltType))
{
component.BoltType = boltType;
}
} }
} }
} }

View File

@@ -25,14 +25,25 @@ namespace Content.Server.Singularity
var entityManager = IoCManager.Resolve<IEntityManager>(); var entityManager = IoCManager.Resolve<IEntityManager>();
var entitySystemManager = IoCManager.Resolve<IEntitySystemManager>(); var entitySystemManager = IoCManager.Resolve<IEntitySystemManager>();
foreach (var comp in entityManager.EntityQuery<EmitterComponent>())
// Turn on emitters
var emitterQuery = entityManager.EntityQueryEnumerator<EmitterComponent>();
var emitterSystem = entitySystemManager.GetEntitySystem<EmitterSystem>();
while (emitterQuery.MoveNext(out var uid, out var emitterComponent))
{ {
entitySystemManager.GetEntitySystem<EmitterSystem>().SwitchOn(comp); //FIXME: This turns on ALL emitters, including APEs. It should only turn on the containment field emitters.
emitterSystem.SwitchOn(uid, emitterComponent);
} }
foreach (var comp in entityManager.EntityQuery<RadiationCollectorComponent>())
// Turn on radiation collectors
var radiationCollectorQuery = entityManager.EntityQueryEnumerator<RadiationCollectorComponent>();
var radiationCollectorSystem = entitySystemManager.GetEntitySystem<RadiationCollectorSystem>();
while (radiationCollectorQuery.MoveNext(out var uid, out var radiationCollectorComponent))
{ {
entitySystemManager.GetEntitySystem<RadiationCollectorSystem>().SetCollectorEnabled(comp.Owner, true, null, comp); radiationCollectorSystem.SetCollectorEnabled(uid, enabled: true, user: null, radiationCollectorComponent);
} }
// Setup PA
foreach (var comp in entityManager.EntityQuery<ParticleAcceleratorControlBoxComponent>()) foreach (var comp in entityManager.EntityQuery<ParticleAcceleratorControlBoxComponent>())
{ {
comp.RescanParts(); comp.RescanParts();

View File

@@ -1,10 +1,12 @@
using System.Threading; using System.Threading;
using Content.Shared.Construction.Prototypes; using Content.Shared.Construction.Prototypes;
using Content.Shared.DeviceLinking;
using Robust.Shared.GameStates; using Robust.Shared.GameStates;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
namespace Content.Shared.Singularity.Components; namespace Content.Shared.Singularity.Components;
@@ -107,6 +109,30 @@ public sealed class EmitterComponent : Component
/// </summary> /// </summary>
[DataField("underpoweredState")] [DataField("underpoweredState")]
public string? UnderpoweredState = "underpowered"; public string? UnderpoweredState = "underpowered";
/// <summary>
/// Signal port that turns on the emitter.
/// </summary>
[DataField("onPort", customTypeSerializer: typeof(PrototypeIdSerializer<SinkPortPrototype>))]
public string OnPort = "On";
/// <summary>
/// Signal port that turns off the emitter.
/// </summary>
[DataField("offPort", customTypeSerializer: typeof(PrototypeIdSerializer<SinkPortPrototype>))]
public string OffPort = "Off";
/// <summary>
/// Signal port that toggles the emitter on or off.
/// </summary>
[DataField("togglePort", customTypeSerializer: typeof(PrototypeIdSerializer<SinkPortPrototype>))]
public string TogglePort = "Toggle";
/// <summary>
/// Map of signal ports to entity prototype IDs of the entity that will be fired.
/// </summary>
[DataField("setTypePorts", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<string, SinkPortPrototype>))]
public Dictionary<string, string> SetTypePorts = new();
} }
[NetSerializable, Serializable] [NetSerializable, Serializable]

View File

@@ -60,3 +60,12 @@ signal-port-description-artifact-analyzer-sender = Analysis console signal sende
signal-port-name-artifact-analyzer-receiver = Pad signal-port-name-artifact-analyzer-receiver = Pad
signal-port-description-artifact-analyzer-receiver = Artifact analyzer signal receiver signal-port-description-artifact-analyzer-receiver = Artifact analyzer signal receiver
signal-port-name-set-particle-delta = Set particle type: delta
signal-port-description-set-particle-delta = Sets the type of particle this device emits to delta.
signal-port-name-set-particle-epsilon = Set particle type: epsilon
signal-port-description-set-particle-epsilon = Sets the type of particle this device emits to epsilon.
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.

View File

@@ -97,3 +97,18 @@
id: B2 id: B2
name: "Input B2" name: "Input B2"
description: "Input B2" description: "Input B2"
- type: sinkPort
id: SetParticleDelta
name: signal-port-name-set-particle-delta
description: signal-port-description-set-particle-delta
- type: sinkPort
id: SetParticleEpsilon
name: signal-port-name-set-particle-epsilon
description: signal-port-description-set-particle-epsilon
- type: sinkPort
id: SetParticleZeta
name: signal-port-name-set-particle-zeta
description: signal-port-description-set-particle-zeta

View File

@@ -151,6 +151,10 @@
- AnomalousParticleDelta - AnomalousParticleDelta
- AnomalousParticleEpsilon - AnomalousParticleEpsilon
- AnomalousParticleZeta - AnomalousParticleZeta
setTypePorts:
SetParticleDelta: AnomalousParticleDelta
SetParticleEpsilon: AnomalousParticleEpsilon
SetParticleZeta: AnomalousParticleZeta
fireBurstSize: 1 fireBurstSize: 1
baseFireBurstDelayMin: 2 baseFireBurstDelayMin: 2
baseFireBurstDelayMax: 6 baseFireBurstDelayMax: 6
@@ -179,6 +183,19 @@
enum.PowerDeviceVisualLayers.Powered: enum.PowerDeviceVisualLayers.Powered:
True: { visible: true } True: { visible: true }
False: { visible: false } False: { visible: false }
- type: DeviceNetwork
deviceNetId: Wireless
receiveFrequencyId: BasicDevice
- type: WirelessNetworkConnection
range: 200
- type: DeviceLinkSink
ports:
- On
- Off
- Toggle
- SetParticleDelta
- SetParticleEpsilon
- SetParticleZeta
- type: entity - type: entity
id: MachineAnomalyGenerator id: MachineAnomalyGenerator

View File

@@ -90,3 +90,13 @@
board: EmitterCircuitboard board: EmitterCircuitboard
- type: GuideHelp - type: GuideHelp
guides: [ Singularity, Power ] guides: [ Singularity, Power ]
- type: DeviceNetwork
deviceNetId: Wireless
receiveFrequencyId: BasicDevice
- type: WirelessNetworkConnection
range: 200
- type: DeviceLinkSink
ports:
- On
- Off
- Toggle